<!DOCTYPE html>
<html lang="en-US" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>快速搭建个人博客网站 | VitePress</title>
    <meta name="description" content="A VitePress site">
    <link rel="preload stylesheet" href="/notebook/assets/style.3dbfd0c2.css" as="style">
    
    <script type="module" src="/notebook/assets/app.8aaa4cbe.js"></script>
    <link rel="preload" href="/notebook/assets/inter-roman-latin.2ed14f66.woff2" as="font" type="font/woff2" crossorigin="">
    <link rel="modulepreload" href="/notebook/assets/chunks/framework.1336c4e5.js">
    <link rel="modulepreload" href="/notebook/assets/chunks/theme.20cddc0c.js">
    <link rel="modulepreload" href="/notebook/assets/Nginx_进阶篇.md.e6b63195.lean.js">
    <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-255ec12d><!--[--><!--]--><!--[--><span tabindex="-1" data-v-ae3e3f51></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-ae3e3f51> Skip to content </a><!--]--><!----><header class="VPNav" data-v-255ec12d data-v-7e5bc4a5><div class="VPNavBar has-sidebar" data-v-7e5bc4a5 data-v-0937f67c><div class="container" data-v-0937f67c><div class="title" data-v-0937f67c><div class="VPNavBarTitle has-sidebar" data-v-0937f67c data-v-86d1bed8><a class="title" href="/notebook/" data-v-86d1bed8><!--[--><!--]--><!--[--><img class="VPImage logo" src="/notebook/Vue.png" alt data-v-8426fc1a><!--]--><!--[-->任硕的文档<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-0937f67c><div class="curtain" data-v-0937f67c></div><div class="content-body" data-v-0937f67c><!--[--><!--]--><div class="VPNavBarSearch search" style="--vp-meta-key:&#39;Meta&#39;;" data-v-0937f67c><!--[--><!----><div id="docsearch"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg class="DocSearch-Search-Icon" width="20" height="20" viewBox="0 0 20 20" aria-label="search icon"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-0937f67c data-v-7f418b0f><span id="main-nav-aria-label" class="visually-hidden" data-v-7f418b0f>Main Navigation</span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>Java学前端</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/HTML+JS.html" data-v-2f2cfafc><!--[-->HTML+JS<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/CSS.html" data-v-2f2cfafc><!--[-->CSS<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/Vue2+%E7%BB%84%E4%BB%B6.html" data-v-2f2cfafc><!--[-->Vue2+组件<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/Vue3+%E7%BB%84%E4%BB%B6.html" data-v-2f2cfafc><!--[-->Vue3+组件<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/React.html" data-v-2f2cfafc><!--[-->React<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>软件测试</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/%E6%B5%8B%E8%AF%95%E5%9F%BA%E7%A1%80.html" data-v-2f2cfafc><!--[-->测试基础<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/%E5%8E%8B%E5%8A%9B%E6%B5%8B%E8%AF%95.html" data-v-2f2cfafc><!--[-->压力测试<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>多线程</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E5%B9%B6%E5%8F%91%20&amp;%20%E5%A4%9A%E7%BA%BF%E7%A8%8B/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-2f2cfafc><!--[-->基础篇<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E5%B9%B6%E5%8F%91%20&amp;%20%E5%A4%9A%E7%BA%BF%E7%A8%8B/%E5%B9%B6%E5%8F%91%E5%AE%8C%E5%96%84.html" data-v-2f2cfafc><!--[-->进阶篇<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>开发工具</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/Chrome.html" data-v-2f2cfafc><!--[-->Chrome<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/IDEA%E5%9F%BA%E7%A1%80.html" data-v-2f2cfafc><!--[-->IDEA基础<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/IDEA%E6%8F%92%E4%BB%B6.html" data-v-2f2cfafc><!--[-->IDEA插件<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/VS%20Code.html" data-v-2f2cfafc><!--[-->VS Code<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>消息中间件</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/RabbitMQ.html" data-v-2f2cfafc><!--[-->RabbitMQ<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/RocketMQ.html" data-v-2f2cfafc><!--[-->RocketMQ<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/Kafka.html" data-v-2f2cfafc><!--[-->Kafka<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/Canal.html" data-v-2f2cfafc><!--[-->Canal<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-0937f67c data-v-f6a63727><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title="toggle dark mode" aria-checked="false" data-v-f6a63727 data-v-82b282f1 data-v-f3c41672><span class="check" data-v-f3c41672><span class="icon" data-v-f3c41672><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-82b282f1><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-82b282f1><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-0937f67c data-v-0394ad82 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/renshuo123/renshuo123.github.io" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink no-icon" href="#" aria-label="twitter" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a><a class="VPSocialLink no-icon" href="https://github.com/" aria-label target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg t="1676028692954" class="icon" ...</path></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-0937f67c data-v-40855f84 data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-a7b5672a><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-a7b5672a><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><!----><!--[--><!--[--><!----><div class="group" data-v-40855f84><div class="item appearance" data-v-40855f84><p class="label" data-v-40855f84>Appearance</p><div class="appearance-action" data-v-40855f84><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title="toggle dark mode" aria-checked="false" data-v-40855f84 data-v-82b282f1 data-v-f3c41672><span class="check" data-v-f3c41672><span class="icon" data-v-f3c41672><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-82b282f1><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-82b282f1><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-40855f84><div class="item social-links" data-v-40855f84><div class="VPSocialLinks social-links-list" data-v-40855f84 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/renshuo123/renshuo123.github.io" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink no-icon" href="#" aria-label="twitter" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a><a class="VPSocialLink no-icon" href="https://github.com/" aria-label target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg t="1676028692954" class="icon" ...</path></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-0937f67c data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav reached-top" data-v-255ec12d data-v-5cfd5582><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-5cfd5582><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-5cfd5582><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-5cfd5582>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-5cfd5582 data-v-18201f51><button data-v-18201f51>Return to top</button><!----></div></div><aside class="VPSidebar" data-v-255ec12d data-v-845b8fc6><div class="curtain" data-v-845b8fc6></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-845b8fc6><span class="visually-hidden" id="sidebar-aria-label" data-v-845b8fc6> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Java</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E6%96%B0%E7%89%B9%E6%80%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java新特性</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E9%9B%86%E5%90%88.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java集合</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java高级</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Linux</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/Linux%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Linux基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/Linux%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Linux新特性</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/Shell.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Shell脚本</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/%E5%AE%9E%E7%94%A8%E8%84%9A%E6%9C%AC.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>实用脚本</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/%E8%BD%AF%E4%BB%B6%E9%83%A8%E7%BD%B2.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>软件部署</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible has-active" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Nginx</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E5%AE%9E%E6%88%98%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>实战篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E9%9D%A2%E8%AF%95%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>面试篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SSM</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/Maven.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Maven</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/Spring.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Spring</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/SpringMVC.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringMVC</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/SpringBatch.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringBatch</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SpringBoot</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E5%BA%94%E7%94%A8%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>应用篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E6%96%B0%E7%89%B9%E6%80%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>新特性</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E8%BF%90%E7%BB%B4&amp;%E5%8E%9F%E7%90%86.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>运维&原理</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SpringCloud</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringCloud</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BF%85%E5%A4%87/Sentinel.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Sentinel</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SpringSecurity</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/SpringSecurity/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringSecurity基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/SpringSecurity/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringSecurity进阶篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/SpringSecurity/%E9%AB%98%E7%BA%A7%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringSecurity高级篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Mybatis & MybatisPlus</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Mybatis&amp;MybatisPlus/Mybatis.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Mybatis</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Mybatis&amp;MybatisPlus/MybatisPlus.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MybatisPlus</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Mybatis&amp;MybatisPlus/JPA.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>JPA</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Git & ChatGPT</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Git.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Git</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Github.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Github</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/ChatGPT.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ChatGPT</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Jenkins.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Jenkins</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Netty.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Netty</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>数据库</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>MySQL</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E4%BC%98%E5%8C%96.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL优化</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E8%AE%BE%E8%AE%A1.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL设计</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E8%BF%90%E7%BB%B4.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL运维</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>分库分表</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>Redis</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E4%BC%98%E5%8C%96.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis优化</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E5%8E%9F%E7%90%86.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis原理</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis高级</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E5%AE%9E%E6%88%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis实战</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/%E6%9C%AC%E5%9C%B0%E7%BC%93%E5%AD%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>本地缓存</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>MongoDB</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MongoDB/%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MongoDB基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MongoDB/%E6%95%B4%E5%90%88.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MongoDB进阶</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>ElasticSearch</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/ElasticSearch/1%E3%80%81ES%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/ElasticSearch/3%E3%80%81ES%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES高级</p><!--]--></a><!----></div><!----></div><!--]--></div></section><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/influxdb.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>InfluxDB</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Neo4j.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Neo4j</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>高并发 & 秒杀 & 分布式</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E5%88%86%E5%B8%83%E5%BC%8F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>分布式理论</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BF%85%E5%A4%87/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>分布式锁</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E7%A7%92%E6%9D%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>秒杀</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E9%AB%98%E5%8F%AF%E7%94%A8.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>高可用</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E9%AB%98%E5%B9%B6%E5%8F%91.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>高并发</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>云原生</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%BA%91%E5%8E%9F%E7%94%9F/Docker.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Docker</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%BA%91%E5%8E%9F%E7%94%9F/K8S.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>K8S</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>可视化 & 监控</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/%E7%9B%91%E6%8E%A7%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>监控基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/%E7%9B%91%E6%8E%A7%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>监控进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/%E5%8F%AF%E8%A7%86%E5%8C%96%E5%A4%A7%E5%B1%8F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>可视化大屏</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/Zabbix.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Zabbix</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>学前端</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>HTML+CSS</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/1%E3%80%81HTML+CSS/HTML%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>HTML基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/1%E3%80%81HTML+CSS/CSS%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>CSS基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/1%E3%80%81HTML+CSS/%E7%BD%91%E9%A1%B5%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>网页进阶</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>JS+TS</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/JS%20%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>JS基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/JS%20%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>JS进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/ES6%20%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES6基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/ES6%20%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES6进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/TypeScript.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>TS基础</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>NodeJS</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/4%E3%80%81Node/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Node基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/4%E3%80%81Node/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Node进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/4%E3%80%81Node/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目实战</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>Vue</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue3/Vue3%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Vue3进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue3/Vue3%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Vue3高级</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue3/Vue3%E6%96%B0%E8%AF%AD%E6%B3%95.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Vue3新语法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue2/Vue2%E9%A1%B9%E7%9B%AE.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目实战</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>小程序</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>小程序基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%BC%98%E5%8C%96.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>小程序优化</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/uniapp.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>uniapp</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%A1%B9%E7%9B%AE.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目实战</p><!--]--></a><!----></div><!----></div><!--]--></div></section><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>计算机基础</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>数据结构</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>操作系统</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>设计模式</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>计算机网络</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/UML.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>UML</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E7%AE%97%E6%B3%95/LeetCode.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>LeetCode</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>项目实战</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>云尚办公</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E4%BA%91%E5%B0%9A%E5%8A%9E%E5%85%AC/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>小兔鲜</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E5%85%94%E9%B2%9C/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E5%85%94%E9%B2%9C/%E8%BF%9B%E9%98%B6%E7%AF%871.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇1</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E5%85%94%E9%B2%9C/%E8%BF%9B%E9%98%B6%E7%AF%872.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇2</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>地图</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>苍穹外卖</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E8%8B%8D%E7%A9%B9%E5%A4%96%E5%8D%96/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>黑马头条</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E8%BF%9B%E9%98%B6%E7%AF%872.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇2</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E9%AB%98%E7%BA%A7%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>高级篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E6%94%AF%E4%BB%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>支付</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%A1%B9%E7%9B%AE%E6%8E%A8%E8%8D%90.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目推荐</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0" data-v-845b8fc6 data-v-9b797284><!----><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/team.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>团队成员</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-255ec12d data-v-669faec9><div class="VPDoc has-sidebar has-aside" data-v-669faec9 data-v-6b87e69f><!--[--><!--]--><div class="container" data-v-6b87e69f><div class="aside" data-v-6b87e69f><div class="aside-curtain" data-v-6b87e69f></div><div class="aside-container" data-v-6b87e69f><div class="aside-content" data-v-6b87e69f><div class="VPDocAside" data-v-6b87e69f data-v-3f215769><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-3f215769 data-v-ff0f39c8><div class="content" data-v-ff0f39c8><div class="outline-marker" data-v-ff0f39c8></div><div class="outline-title" data-v-ff0f39c8>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-ff0f39c8><span class="visually-hidden" id="doc-outline-aria-label" data-v-ff0f39c8> Table of Contents for current page </span><ul class="root" data-v-ff0f39c8 data-v-d0ee3533><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-3f215769></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-6b87e69f><div class="content-container" data-v-6b87e69f><!--[--><!--]--><!----><main class="main" data-v-6b87e69f><div style="position:relative;" class="vp-doc _notebook_Nginx_%E8%BF%9B%E9%98%B6%E7%AF%87" data-v-6b87e69f><div><h1 id="快速搭建个人博客网站" tabindex="-1">快速搭建个人博客网站 <a class="header-anchor" href="#快速搭建个人博客网站" aria-label="Permalink to &quot;快速搭建个人博客网站&quot;">​</a></h1><h2 id="前言" tabindex="-1">前言 <a class="header-anchor" href="#前言" aria-label="Permalink to &quot;前言&quot;">​</a></h2><p>为什么选择搭建个人博客？一方面是各个平台经常下架原创文章，另一个方面是为了熟悉整个建站流程。</p><p>通过搭建个人博客，我们可以自由的发表文章不用担心下架，而且可以锻炼个人的SEO优化能力，不管是运维还是运营这块对个人的技术提升有着很大的帮助。</p><p>本篇文章记录了网站从零到一的过程，希望你也能根据本篇文章搭建出属于自己的网站。大家有疑问可以一起讨论。</p><p>下面开始正题。</p><h2 id="环境介绍" tabindex="-1">环境介绍 <a class="header-anchor" href="#环境介绍" aria-label="Permalink to &quot;环境介绍&quot;">​</a></h2><table><thead><tr><th>资源</th><th>说明</th></tr></thead><tbody><tr><td>centos</td><td>v7.2</td></tr><tr><td>docker</td><td>快速部署项目环境</td></tr><tr><td>nginx</td><td>反向代理，同时配置https证书</td></tr><tr><td>halo</td><td>v1.4.2，开源博客项目</td></tr><tr><td>Let&#39;s Encrypt 免费证书</td><td>配置https</td></tr></tbody></table><h2 id="效果演示" tabindex="-1">效果演示 <a class="header-anchor" href="#效果演示" aria-label="Permalink to &quot;效果演示&quot;">​</a></h2><blockquote><p><a href="https://yangwq.cn/" target="_blank" rel="noreferrer">https://yangwq.cn/</a></p></blockquote><h2 id="前置环境安装" tabindex="-1">前置环境安装 <a class="header-anchor" href="#前置环境安装" aria-label="Permalink to &quot;前置环境安装&quot;">​</a></h2><h3 id="docker安装" tabindex="-1">Docker安装 <a class="header-anchor" href="#docker安装" aria-label="Permalink to &quot;Docker安装&quot;">​</a></h3><p>参考：</p><blockquote><p><a href="https://www.cnblogs.com/winkin/p/14083574.html" target="_blank" rel="noreferrer">https://www.cnblogs.com/winkin/p/14083574.html</a></p></blockquote><h3 id="halo安装" tabindex="-1">halo安装 <a class="header-anchor" href="#halo安装" aria-label="Permalink to &quot;halo安装&quot;">​</a></h3><h4 id="准备halo配置文件" tabindex="-1">准备halo配置文件 <a class="header-anchor" href="#准备halo配置文件" aria-label="Permalink to &quot;准备halo配置文件&quot;">​</a></h4><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 下载配置文件到 </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">halo</span><span style="color:#89DDFF;">/.</span><span style="color:#A6ACCD;">halo 目录</span></span>
<span class="line"><span style="color:#A6ACCD;">curl </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">o </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">halo</span><span style="color:#89DDFF;">/.</span><span style="color:#A6ACCD;">halo</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">application</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">yaml </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">create</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">dirs https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">dl</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">halo</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">run</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">config</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">application</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">template</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">yaml</span></span></code></pre></div><p>修改配置文件，将数据库调整为mysql，默认是h2（可选） <img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.30/202207311519916.png" alt="image-20220731151944850" style="zoom:67%;"></p><p>将上面h2的数据库注释，并把mysql的配置打开，注意，需要提前在mysql建立数据库 halodb，相关的数据库表halo会自动生成，如果mysql 和 halo都是容器创建的，这里配置的mysqlip应该是mysql容器内部的ip。</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 查看mysql容器的ip，mysql</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">prod替换成mysql容器名称或者容器id</span></span>
<span class="line"><span style="color:#A6ACCD;">docker inspect </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">format</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">{{.NetworkSettings.IPAddress}}</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;"> mysql</span></span></code></pre></div><p>修改后： <img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.30/202207311519800.png" alt="image-20220731151958699" style="zoom:67%;">下载并安装halo</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;"># 拉取halo镜像</span></span>
<span class="line"><span style="color:#A6ACCD;">docker pull ruibaby/halo</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;"># 运行halo</span></span>
<span class="line"><span style="color:#A6ACCD;"># -p 8090:8090 指定宿主机端口与容器端口映射，这里是将宿主机的8090映射到docker的8090</span></span>
<span class="line"><span style="color:#A6ACCD;"># -v /home/halo/.halo:/root/.halo 挂载halo配置文件，我们在上一步下载了配置文件在宿主机的/home/halo/.halo</span></span>
<span class="line"><span style="color:#A6ACCD;">docker run --rm -it -d --name halo -p 8090:8090  -v /home/halo/.halo:/root/.halo ruibaby/halo</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">## 查看容器状态，确认halo是否启动成功，如果启动失败需要检查下数据库连接</span></span>
<span class="line"><span style="color:#A6ACCD;">docker ps</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;"># 配置防火墙，注意，阿里云需要同时配置安全组8090端口</span></span>
<span class="line"><span style="color:#A6ACCD;"># 开放8090端口</span></span>
<span class="line"><span style="color:#A6ACCD;">firewall-cmd --permanent --add-port=8090/tcp</span></span>
<span class="line"><span style="color:#A6ACCD;">#重启防火墙(修改配置后要重启防火墙)</span></span>
<span class="line"><span style="color:#A6ACCD;">firewall-cmd --reload</span></span></code></pre></div><p>正常情况应该如下： <img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbuf7P8uhfWcPKiax4mic0Hf46d5terOWJzLr8F9yFFRdiaBTnTYgEMBqxCDUfguiama6vbAje2Kxq2We2A/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>经过上面的步骤创建的halo还不能通过外部ip访问，我们现在配置一个nginx进行代理</p><h3 id="nginx安装" tabindex="-1">nginx安装 <a class="header-anchor" href="#nginx安装" aria-label="Permalink to &quot;nginx安装&quot;">​</a></h3><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 下载nginx镜像</span></span>
<span class="line"><span style="color:#A6ACCD;">docker pull nginx</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 启动nginx</span></span>
<span class="line"><span style="color:#A6ACCD;">docker run </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">p </span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;">:</span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">name nginx </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d nginx</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 我们需要nginx使用我们自定义的配置，最方便的方法将nginx现在有的配置复制一份到宿主机目录 </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx </span></span>
<span class="line"><span style="color:#A6ACCD;">docker container cp nginx:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 移除我们刚创建的nginx，重新以宿主机配置目录启动</span></span>
<span class="line"><span style="color:#A6ACCD;">docker stop nginx</span></span>
<span class="line"><span style="color:#A6ACCD;">docker rm nginx</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 编辑 conf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">d 下的default</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">conf 文件，默认转发到halo端口，ip地址为本机ip</span></span>
<span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    root   </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">usr</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">share</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">html</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    index  index</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html index</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">htm</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">改为，</span><span style="color:#F78C6C;">10.0.2.5</span><span style="color:#A6ACCD;"> 为本机ip，通过命令 ip addr 查看，端口是halo的端口：</span></span>
<span class="line"><span style="color:#A6ACCD;"> location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">     proxy_pass http:</span><span style="color:#89DDFF;">//</span><span style="color:#F78C6C;">10.0.2.5</span><span style="color:#A6ACCD;">:</span><span style="color:#F78C6C;">8090</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 重新创建nginx</span></span>
<span class="line"><span style="color:#A6ACCD;">docker run </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">p </span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;">:</span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">name nginx </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">logs:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">var</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">log</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">conf:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">conf </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">conf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">d:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">conf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">d </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d nginx</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置防火墙，注意，阿里云需要同时配置安全组</span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;">端口</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 开放</span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;">端口</span></span>
<span class="line"><span style="color:#A6ACCD;">firewall</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">cmd </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">permanent </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">add</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">80</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">tcp</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;">重启防火墙</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">修改配置后要重启防火墙</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">firewall</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">cmd </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">reload</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 到这里，我们可以通过ip访问halo了</span></span></code></pre></div><p>到这一步如果不能使用ip直接访问，首先确定halo启动成功没，然后查看nginx配置是否正确，最后再检查防火墙和安全组。</p><h2 id="域名及网站备案" tabindex="-1">域名及网站备案 <a class="header-anchor" href="#域名及网站备案" aria-label="Permalink to &quot;域名及网站备案&quot;">​</a></h2><p>目前我们只能通过ip访问halo，我们可以通过配置域名进行访问。</p><p>首先我们得申请一个域名：</p><blockquote><p><a href="https://wanwang.aliyun.com/domain" target="_blank" rel="noreferrer">https://wanwang.aliyun.com/domain</a></p></blockquote><p>申请完成后进行备案：</p><blockquote><p><a href="https://beian.aliyun.com/" target="_blank" rel="noreferrer">https://beian.aliyun.com/</a></p></blockquote><p>备案注意事项：</p><ul><li>如果处于异地工作的情况，建议备案地点选择老家，而且手上要有老家的手机号，如果选择异地的话，需要你提供临时居住证之类比较麻烦。</li><li>阿里云备案时间在一周左右，一般提交申请会有人找你确认信息，之后按备案流程走就行了。</li></ul><h2 id="配置https" tabindex="-1">配置https <a class="header-anchor" href="#配置https" aria-label="Permalink to &quot;配置https&quot;">​</a></h2><p>一般情况证书是需要购买的，但是也有一些平台提供了免费证书，阿里云也有一年的免费证书，但是阿里云证书只能单个域名使用，如果要通配符证书是需要付费的。而Let’s Encrypt 证书即可以免费申请证书，又支持通配符，是个人开发者的上选。</p><p>这里我们通过github项目配置免费证书（也可以手动安装，不过自动安装比较方便，下面两种方式都会提到）：<code>letencrypt-certbot</code></p><blockquote><p><a href="https://github.com/ywdblog/certbot-letencrypt-wildcardcertificates-alydns-au" target="_blank" rel="noreferrer">https://github.com/ywdblog/certbot-letencrypt-wildcardcertificates-alydns-au</a></p></blockquote><p>使用此项目前我们配置一下前置环境：certbot 和 git</p><h3 id="安装git" tabindex="-1">安装git <a class="header-anchor" href="#安装git" aria-label="Permalink to &quot;安装git&quot;">​</a></h3><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">yum install git</span></span></code></pre></div><h3 id="安装certbot" tabindex="-1">安装certbot <a class="header-anchor" href="#安装certbot" aria-label="Permalink to &quot;安装certbot&quot;">​</a></h3><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 安装certbot，中间需要输入y确认</span></span>
<span class="line"><span style="color:#A6ACCD;">yum install epel</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">release</span></span>
<span class="line"><span style="color:#A6ACCD;">yum install certbot </span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 查看版本，如果安装正常会显示版本号</span></span>
<span class="line"><span style="color:#A6ACCD;">certbot </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">version</span></span></code></pre></div><h3 id="申请证书" tabindex="-1">申请证书 <a class="header-anchor" href="#申请证书" aria-label="Permalink to &quot;申请证书&quot;">​</a></h3><p>特别注意的是，这里需要主机把80端口和443端口开放，上面我们已经开放了80端口，这里开放443端口就行了</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置防火墙，注意，阿里云需要同时配置安全组</span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;">端口</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 开放</span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;">端口</span></span>
<span class="line"><span style="color:#A6ACCD;">firewall</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">cmd </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">permanent </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">add</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">443</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">tcp</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;">重启防火墙</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">修改配置后要重启防火墙</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">firewall</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">cmd </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">reload</span></span></code></pre></div><p>重要提示：为避免遇到操作次数的限制，加入 dry-run 参数，可以避免操作限制，等执行无误后，再进行真实的 renew 操作</p><h3 id="手动安装证书-手动续期" tabindex="-1">手动安装证书+手动续期 <a class="header-anchor" href="#手动安装证书-手动续期" aria-label="Permalink to &quot;手动安装证书+手动续期&quot;">​</a></h3><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 申请证书，需要填入你的邮箱和域名</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">dry</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">run 测试使用不会生成证书，我们先用这个命令看是否成功</span></span>
<span class="line"><span style="color:#A6ACCD;">certbot certonly </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">email 你的邮箱</span><span style="color:#89DDFF;">@</span><span style="color:#A6ACCD;">qq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d </span><span style="color:#89DDFF;">*.</span><span style="color:#A6ACCD;">域名</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d 域名</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">preferred</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">challenges dns</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">01</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">server https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">acme</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v02</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">api</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">org</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">directory </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">dry</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">run</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 如果没有错误信息，去掉</span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">dry</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">run真正生成证书</span></span>
<span class="line"><span style="color:#A6ACCD;">certbot certonly </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">email 你的邮箱</span><span style="color:#89DDFF;">@</span><span style="color:#A6ACCD;">qq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d </span><span style="color:#89DDFF;">*.</span><span style="color:#A6ACCD;">域名</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d 域名</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">preferred</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">challenges dns</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">01</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">server https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">acme</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v02</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">api</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">org</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">directory</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 手动续期</span></span>
<span class="line"><span style="color:#A6ACCD;">certbot renew</span></span></code></pre></div><p>安装过程中，需要确认选项，讲一下手动安装的重点： <img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbuf7P8uhfWcPKiax4mic0Hf46dYuCDbOVlAWVA7soZaPeTqcDoibGBicnnYXrzLtEicEoicAIljM22A8GibwQ/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"> 安装成功后显示： <img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbuf7P8uhfWcPKiax4mic0Hf46dNOWtdk8UINOOqJcmK2JM7YvRDYzYwQa5QM46V7HfYVc9aaV2iajfhDA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>注意：证书90天后过期，我们手动续期的话比较麻烦，而且每次需要手动去DNS解析列表创建对应的记录，所以推荐下面的自动续期方式</p><h3 id="通过apikey-和secret生成证书-自动续期" tabindex="-1">通过apikey 和secret生成证书+自动续期 <a class="header-anchor" href="#通过apikey-和secret生成证书-自动续期" aria-label="Permalink to &quot;通过apikey 和secret生成证书+自动续期&quot;">​</a></h3><p>首先获取api key 和secret：</p><blockquote><p><a href="https://help.aliyun.com/knowledge_detail/38738.html" target="_blank" rel="noreferrer">https://help.aliyun.com/knowledge_detail/38738.html</a></p></blockquote><p>这种方式其实是利用你开放的api key调用阿里云提供的接口，所以保险起见我们创建一个权限很小的用户就行了。</p><p>流程：</p><ul><li>为了安全，我们需要先创建RAM用户，配置一个权限小的用户；</li><li>给新创建的用户配置 AliyunDNSFullAccess（管理云解析（DNS）） 的权限；</li><li>获取apikey 和 secret。</li></ul><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 新建一个目标，拉取项目</span></span>
<span class="line"><span style="color:#A6ACCD;">mkdir </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">certbot</span></span>
<span class="line"><span style="color:#A6ACCD;">cd </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">certbot</span></span>
<span class="line"><span style="color:#A6ACCD;">git clone https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">github</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">ywdblog</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">certbot</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">letencrypt</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">wildcardcertificates</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">alydns</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">au</span></span>
<span class="line"><span style="color:#A6ACCD;">cd certbot</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">letencrypt</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">wildcardcertificates</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">alydns</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">au</span></span>
<span class="line"><span style="color:#A6ACCD;">chmod </span><span style="color:#F78C6C;">0777</span><span style="color:#A6ACCD;"> au</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sh</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 编辑au</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sh，加入我们上面申请的key</span></span>
<span class="line"><span style="color:#A6ACCD;">vi au</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">sh</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;">填写阿里云的AccessKey ID及AccessKey Secret</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;">如何申请见https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">help</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">aliyun</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">knowledge_detail</span><span style="color:#89DDFF;">/</span><span style="color:#F78C6C;">38738</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html</span></span>
<span class="line"><span style="color:#A6ACCD;">ALY_KEY</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">ALY_TOKEN</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 运行命令，加上</span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">dry</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">run 测试，如果没问题去掉 </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">dry</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">run 执行，脚本目录就是我们上面创建的 </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">certbot</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">certbot</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">letencrypt</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">wildcardcertificates</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">alydns</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">au</span></span>
<span class="line"><span style="color:#A6ACCD;">certbot certonly  </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d </span><span style="color:#89DDFF;">*.</span><span style="color:#A6ACCD;">yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">preferred</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">challenges dns</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">01</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">email </span><span style="color:#F78C6C;">1075976874</span><span style="color:#89DDFF;">@</span><span style="color:#A6ACCD;">qq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com  </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">auth</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">hook </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/脚本目录/au.sh python aly add</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">cleanup</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">hook </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/脚本目录/au.sh python aly clean</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">dry</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">run</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置自动续期，使用crontab实现</span></span>
<span class="line"><span style="color:#A6ACCD;">vi </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">crontab</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 加入以下命令，这个命令就是每周执行一次脚本，如果需要续期就会自动更新</span></span>
<span class="line"><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> root certbot renew </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">preferred</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">challenges dns </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">deploy</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">hook  </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">docker restart nginx</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">auth</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">hook </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/脚本目录/au.sh python aly add</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">cleanup</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">hook </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/脚本目录/au.sh python aly clean</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">manual</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">public</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">ip</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">logging</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">ok</span><span style="color:#89DDFF;">;</span></span></code></pre></div><p>到这一步我们证书生成成功了，同样存放在 /etc/letsencrypt/live/yangwq.cn/ 目录，注意这里的文件是软链接，我们实际上的文件在 etc/letsencrypt/archive/yangwq.cn 目录</p><h3 id="nginx安装证书" tabindex="-1">nginx安装证书 <a class="header-anchor" href="#nginx安装证书" aria-label="Permalink to &quot;nginx安装证书&quot;">​</a></h3><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 编辑conf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">d 下的default</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">conf</span></span>
<span class="line"><span style="color:#A6ACCD;">server </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    listen       </span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;"> default</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    server_name yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> http自动转https</span></span>
<span class="line"><span style="color:#A6ACCD;">    rewrite ^(</span><span style="color:#89DDFF;">.*</span><span style="color:#A6ACCD;">)$  https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">$host$</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;"> permanent</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">server </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    listen </span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;"> ssl</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    server_name yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置站点证书文件地址</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_certificate  </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">archive</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">fullchain1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">pem</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置证书私钥</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_certificate_key  </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">archive</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">privkey1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">pem</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置服务器可使用的加密算法</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_ciphers </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 指定服务器密码算法在优先于客户端密码算法时，使用 SSLv3 和 TLS 协议</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_prefer_server_ciphers  on</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> ssl 版本 可用 SSLv2</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">SSLv3</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">TLSv1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">TLSv1</span><span style="color:#F78C6C;">.1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">TLSv1</span><span style="color:#F78C6C;">.2</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> ie6 只支持 SSLv2</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">SSLv3 但是存在安全问题</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> 故不支持</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_protocols        TLSv1 TLSv1</span><span style="color:#F78C6C;">.1</span><span style="color:#A6ACCD;"> TLSv1</span><span style="color:#F78C6C;">.2</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 配置 TLS 握手后生成的 session 缓存空间大小 </span><span style="color:#F78C6C;">1m</span><span style="color:#A6ACCD;"> 大约能存储 </span><span style="color:#F78C6C;">4000</span><span style="color:#A6ACCD;"> 个 session</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_session_cache          shared:SSL:</span><span style="color:#F78C6C;">50m</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> session 超时时间</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_session_timeout        </span><span style="color:#F78C6C;">1d</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 负载均衡时使用 此处暂时关闭 详情见 https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">imququ</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">optimize</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">tls</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">handshake</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1.5.9</span><span style="color:#A6ACCD;"> 及以上支持</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_session_tickets off</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 浏览器可能会在建立 TLS 连接时在线验证证书有效性，从而阻塞 TLS 握手，拖慢整体速度。OCSP stapling 是一种优化措施，服务端通过它可以在证书链中封装证书颁发机构的 OCSP（Online Certificate Status Protocol）响应，从而让浏览器跳过在线查询。服务端获取 OCSP 一方面更快（因为服务端一般有更好的网络环境），另一方面可以更好地缓存 以上内容来自 https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">imququ</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">my</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">conf</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">for</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">wpo</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1.3.7</span><span style="color:#A6ACCD;"> 及以上支持</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_stapling               on</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_stapling_verify        on</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 根证书 </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> 中间证书</span></span>
<span class="line"><span style="color:#A6ACCD;">    ssl_trusted_certificate    </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">archive</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">yangwq</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">cn</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">fullchain1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">pem</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> HSTS 可以告诉浏览器，在指定的 max</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">age 内，始终通过 HTTPS 访问该域名。即使用户自己输入 HTTP 的地址，或者点击了 HTTP 链接，浏览器也会在本地替换为 HTTPS 再发送请求 相关配置见 https:</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">imququ</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">com</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">sth</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">about</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">switch</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">to</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">https</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html</span></span>
<span class="line"><span style="color:#A6ACCD;">    add_header Strict</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">Transport</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">Security max</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">age</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">60</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 在此填写原本 http 协议中的配置</span></span>
<span class="line"><span style="color:#A6ACCD;">    location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">                           </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 定义首页索引目录和名称</span></span>
<span class="line"><span style="color:#A6ACCD;">        proxy_pass http:</span><span style="color:#89DDFF;">//</span><span style="color:#F78C6C;">172.24.35.32</span><span style="color:#A6ACCD;">:</span><span style="color:#F78C6C;">8080</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">  error_page   </span><span style="color:#F78C6C;">500</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">502</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">503</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">504</span><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">/</span><span style="color:#F78C6C;">50x</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    location </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">/</span><span style="color:#F78C6C;">50x</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">                </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;">重定向错误页面到 </span><span style="color:#89DDFF;">/</span><span style="color:#F78C6C;">50x</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">html</span></span>
<span class="line"><span style="color:#A6ACCD;">        root   </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">usr</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">share</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">html</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>注意：将上面yangwq.cn相关的路径换成你的域名路径。</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 为了让nginx能访问到我们刚生成的证书，需要重新挂载证书路径到nginx</span></span>
<span class="line"><span style="color:#A6ACCD;">docker stop nginx</span></span>
<span class="line"><span style="color:#A6ACCD;">docker rm nginx</span></span>
<span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 运行nginx</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">此处加入了</span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;">端口和证书路径</span></span>
<span class="line"><span style="color:#A6ACCD;">docker run </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">p </span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;">:</span><span style="color:#F78C6C;">80</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">p </span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;">:</span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">name nginx </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">logs:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">var</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">log</span><span style="color:#89DDFF;">//</span><span style="color:#A6ACCD;">nginx </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">conf:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">conf </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">home</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">conf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">d:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">nginx</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">conf</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">d </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">v </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">archive</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">:</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">etc</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">letsencrypt</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">archive</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">\</span></span>
<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">d nginx</span></span></code></pre></div><p>此时我们就可以通过https域名访问项目了，而且这个时候也可以新建二级域名访问项目的（二级域名同样是https）。</p><h1 id="lua" tabindex="-1">Lua <a class="header-anchor" href="#lua" aria-label="Permalink to &quot;Lua&quot;">​</a></h1><h2 id="lua-概览" tabindex="-1">Lua 概览 <a class="header-anchor" href="#lua-概览" aria-label="Permalink to &quot;Lua 概览&quot;">​</a></h2><h3 id="概念" tabindex="-1">概念 <a class="header-anchor" href="#概念" aria-label="Permalink to &quot;概念&quot;">​</a></h3><blockquote><p>Lua是一种轻量、小巧的脚本语言，用标准C语言编写并以源代码形式开发。设计的目的是为了嵌入到其他应用程序中，从而为应用程序提供灵活的扩展和定制功能。</p></blockquote><h3 id="特性" tabindex="-1">特性 <a class="header-anchor" href="#特性" aria-label="Permalink to &quot;特性&quot;">​</a></h3><blockquote><p>轻量级：Lua用标准C语言编写并以源代码形式开发，编译后仅仅一百余千字节，可以很方便的嵌入到其他程序中</p></blockquote><blockquote><p>可扩展：Lua提供非常丰富易于使用的扩展接口和机制，由宿主语言(通常是C或C++)提供功能，Lua可以使用它们，就像内置的功能一样。</p></blockquote><blockquote><p>支持面向过程编程和函数式编程</p></blockquote><h3 id="应用场景" tabindex="-1">应用场景 <a class="header-anchor" href="#应用场景" aria-label="Permalink to &quot;应用场景&quot;">​</a></h3><blockquote><p>Lua在不同的系统中得到大量应用，游戏开发、独立应用脚本、web应用脚本、扩展和数据库插件、系统安全</p></blockquote><h2 id="lua的安装" tabindex="-1">Lua的安装 <a class="header-anchor" href="#lua的安装" aria-label="Permalink to &quot;Lua的安装&quot;">​</a></h2><p>在linux上安装Lua非常简单，只需要下载源码包并在终端解压、编译即可使用。</p><p>Lua的官网地址为:<code>https://www.lua.org</code></p><p>点击download可以找到对应版本的下载地址，我们本次课程采用的是lua-5.3.5,其对应的资源链接地址为<a href="https://www.lua.org/ftp/lua-5.4.1.tar.gz,%E4%B9%9F%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8wget%E5%91%BD%E4%BB%A4%E7%9B%B4%E6%8E%A5%E4%B8%8B%E8%BD%BD:" target="_blank" rel="noreferrer">https://www.lua.org/ftp/lua-5.4.1.tar.gz,也可以使用wget命令直接下载:</a></p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">wget https://www.lua.org/ftp/lua-5.4.1.tar.gz</span></span></code></pre></div><p>编译安装</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">cd lua-5.4.1</span></span>
<span class="line"><span style="color:#A6ACCD;">make linux test</span></span>
<span class="line"><span style="color:#A6ACCD;">make install</span></span></code></pre></div><p>如果在执行make linux test失败，说明当前系统缺少libreadline-dev依赖包，需要通过命令来进行安装</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">yum install -y readline-devel</span></span></code></pre></div><p>验证是否安装成功</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">lua -v</span></span></code></pre></div><h2 id="第一个lua程序" tabindex="-1">第一个Lua程序 <a class="header-anchor" href="#第一个lua程序" aria-label="Permalink to &quot;第一个Lua程序&quot;">​</a></h2><blockquote><p>Lua和C/C++语法非常相似，整体上比较清晰，简洁。条件语句、循环语句、函数调用都与C/C++基本一致。如果对C/C++不太熟悉的同学来说，也没关系，因为天下语言是一家，基本上理解起来都不会太困难</p></blockquote><p>大家需要知道的是，Lua有两种交互方式，分别是:交互式和脚本式，这两者的区别，下面我们分别来讲解下：</p><h3 id="lua命令行" tabindex="-1">Lua命令行 <a class="header-anchor" href="#lua命令行" aria-label="Permalink to &quot;Lua命令行&quot;">​</a></h3><p>交互式是指可以在命令行输入程序，然后回车就可以看到运行的效果。</p><p>Lua交互式编程模式可以通过命令lua -i 或lua来启用:</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301190956788.png" alt="image-20230119095616724" style="zoom:67%;"><p>在命令行中key输入如下命令，并按回车,会有输出在控制台：</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301190956647.png" alt="image-20230119095645567" style="zoom:67%;"><h3 id="lua-脚本" tabindex="-1">Lua 脚本 <a class="header-anchor" href="#lua-脚本" aria-label="Permalink to &quot;Lua 脚本&quot;">​</a></h3><p>脚本式是将代码保存到一个以lua为扩展名的文件中并执行的方式。</p><p>方式一:</p><p>我们需要一个文件名为 hello.lua,然后通过命令 <code>lua hello.lua</code>来执行，会在控制台输出对应的结果。</p><p>hello.lua</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">print(&quot;Hello World!!&quot;)</span></span></code></pre></div><p>将hello.lua做如下修改</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">#!/usr/local/bin/lua</span></span>
<span class="line"><span style="color:#A6ACCD;">print(&quot;Hello World!!!&quot;)</span></span></code></pre></div><p>第一行用来指定Lua解释器所在位置为 /usr/local/bin/lua，加上#号标记解释器会忽略它。一般情况下#!就是用来指定用哪个程序来运行本文件。但是hello.lua并不是一个可执行文件，需要通过chmod来设置可执行权限，最简单的方式为:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">chmod 755 hello.lua</span></span></code></pre></div><p>然后执行该文件</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">./hello.lua</span></span></code></pre></div><h3 id="注意事项" tabindex="-1">注意事项 <a class="header-anchor" href="#注意事项" aria-label="Permalink to &quot;注意事项&quot;">​</a></h3><p>补充一点，如果想在交互式中运行脚本式的hello.lua中的内容，我们可以使用一个dofile函数，如：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">dofile(&quot;lua_demo/hello.lua&quot;)</span></span></code></pre></div><p>注意:在Lua语言中，连续语句之间的分隔符并不是必须的，也就是说后面不需要加分号，当然加上也不会报错，</p><p>在Lua语言中，表达式之间的换行也起不到任何作用。如以下四个写法，其实都是等效的</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">-- 写法一</span></span>
<span class="line"><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">b</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">+</span><span style="color:#F78C6C;">2</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 写法二</span></span>
<span class="line"><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">b</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">+</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 写法三</span></span>
<span class="line"><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">; b</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">+</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 写法四</span></span>
<span class="line"><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;"> b</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">a</span><span style="color:#89DDFF;">+</span><span style="color:#F78C6C;">2</span></span></code></pre></div><p>不建议使用第四种方式，可读性太差。</p><h2 id="lua的注释" tabindex="-1">Lua的注释 <a class="header-anchor" href="#lua的注释" aria-label="Permalink to &quot;Lua的注释&quot;">​</a></h2><p>关于Lua的注释要分两种，第一种是单行注释，第二种是多行注释。</p><p>单行注释的语法为：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">--注释内容</span></span></code></pre></div><p>多行注释的语法为:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">--[[</span></span>
<span class="line"><span style="color:#A6ACCD;">	注释内容</span></span>
<span class="line"><span style="color:#A6ACCD;">	注释内容</span></span>
<span class="line"><span style="color:#A6ACCD;">--]]</span></span></code></pre></div><p>如果想取消多行注释，只需要在第一个--之前在加一个-即可，如：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">---[[</span></span>
<span class="line"><span style="color:#A6ACCD;">	注释内容</span></span>
<span class="line"><span style="color:#A6ACCD;">	注释内容</span></span>
<span class="line"><span style="color:#A6ACCD;">--]]</span></span></code></pre></div><h2 id="标识符" tabindex="-1">标识符 <a class="header-anchor" href="#标识符" aria-label="Permalink to &quot;标识符&quot;">​</a></h2><p>换句话说标识符就是我们的变量名，Lua定义变量名以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上0个或多个字母，下划线，数字（0到9）。这块建议大家最好不要使用下划线加大写字母的标识符，因为Lua的保留字也是这样定义的，容易发生冲突。注意Lua是区分大小写字母的。</p><h2 id="关键字" tabindex="-1">关键字 <a class="header-anchor" href="#关键字" aria-label="Permalink to &quot;关键字&quot;">​</a></h2><p>下列是Lua的关键字，大家在定义常量、变量或其他用户自定义标识符都要避免使用以下这些关键字：</p><table><thead><tr><th>and</th><th>break</th><th>do</th><th>else</th></tr></thead><tbody><tr><td>elseif</td><td>end</td><td>false</td><td>for</td></tr><tr><td>function</td><td>if</td><td>in</td><td>local</td></tr><tr><td>nil</td><td>not</td><td>or</td><td>repeat</td></tr><tr><td>return</td><td>then</td><td>true</td><td>until</td></tr><tr><td>while</td><td>goto</td><td></td><td></td></tr></tbody></table><p>一般约定，以下划线开头连接一串大写字母的名字（比如 _VERSION）被保留用于 Lua 内部全局变量。这个也是上面我们不建议这么定义标识符的原因。</p><h2 id="运算符" tabindex="-1">运算符 <a class="header-anchor" href="#运算符" aria-label="Permalink to &quot;运算符&quot;">​</a></h2><p>Lua中支持的运算符有算术运算符、关系运算符、逻辑运算符、其他运算符。</p><p>算术运算符:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">+   加法</span></span>
<span class="line"><span style="color:#A6ACCD;">-	减法</span></span>
<span class="line"><span style="color:#A6ACCD;">*	乘法</span></span>
<span class="line"><span style="color:#A6ACCD;">/	除法</span></span>
<span class="line"><span style="color:#A6ACCD;">%	取余</span></span>
<span class="line"><span style="color:#A6ACCD;">^	乘幂</span></span>
<span class="line"><span style="color:#A6ACCD;">-	负号</span></span></code></pre></div><p>例如:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">10+20	--&gt;30</span></span>
<span class="line"><span style="color:#A6ACCD;">20-10	--&gt;10</span></span>
<span class="line"><span style="color:#A6ACCD;">10*20	--&gt;200</span></span>
<span class="line"><span style="color:#A6ACCD;">20/10	--&gt;2</span></span>
<span class="line"><span style="color:#A6ACCD;">3%2		--&gt;1</span></span>
<span class="line"><span style="color:#A6ACCD;">10^2	--&gt;100</span></span>
<span class="line"><span style="color:#A6ACCD;">-10		--&gt;-10</span></span></code></pre></div><p>关系运算符</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">==	等于</span></span>
<span class="line"><span style="color:#A6ACCD;">~=	不等于</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;	大于</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;	小于</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;=	大于等于</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;=	小于等于</span></span></code></pre></div><p>例如:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">10==10		--&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">10~=10		--&gt;false</span></span>
<span class="line"><span style="color:#A6ACCD;">20&gt;10		--&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">20&lt;10		--&gt;false</span></span>
<span class="line"><span style="color:#A6ACCD;">20&gt;=10		--&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">20&lt;=10		--&gt;false</span></span></code></pre></div><p>逻辑运算符</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">and	逻辑与	 A and B     &amp;&amp;   </span></span>
<span class="line"><span style="color:#A6ACCD;">or	逻辑或	 A or B     ||</span></span>
<span class="line"><span style="color:#A6ACCD;">not	逻辑非  取反，如果为true,则返回false  !</span></span></code></pre></div><p>逻辑运算符可以作为if的判断条件，返回的结果如下:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">A = true</span></span>
<span class="line"><span style="color:#A6ACCD;">B = true</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">A and B	--&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">A or  B --&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">not A 	--&gt;false</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">A = true</span></span>
<span class="line"><span style="color:#A6ACCD;">B = false</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">A and B	--&gt;false</span></span>
<span class="line"><span style="color:#A6ACCD;">A or  B --&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">not A 	--&gt;false</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">A = false</span></span>
<span class="line"><span style="color:#A6ACCD;">B = true</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">A and B	--&gt;false</span></span>
<span class="line"><span style="color:#A6ACCD;">A or  B --&gt;true</span></span>
<span class="line"><span style="color:#A6ACCD;">not A 	--&gt;true</span></span></code></pre></div><p>其他运算符</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">..	连接两个字符串</span></span>
<span class="line"><span style="color:#A6ACCD;">#	一元预算法，返回字符串或表的长度</span></span></code></pre></div><p>例如:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&gt; &quot;HELLO &quot;..&quot;WORLD&quot;		--&gt;HELLO WORLD</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt; #&quot;HELLO&quot;			--&gt;5</span></span></code></pre></div><h2 id="全局变量-局部变量" tabindex="-1">全局变量&amp;局部变量 <a class="header-anchor" href="#全局变量-局部变量" aria-label="Permalink to &quot;全局变量&amp;局部变量&quot;">​</a></h2><p>在Lua语言中，全局变量无须声明即可使用。在默认情况下，变量总是认为是全局的，如果未提前赋值，默认为nil:</p><p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301181923006.png" alt="1604650220670"></p><p>要想声明一个局部变量，需要使用local来声明</p><p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301181923034.png" alt="1604650235860"></p><h2 id="lua数据类型" tabindex="-1">Lua数据类型 <a class="header-anchor" href="#lua数据类型" aria-label="Permalink to &quot;Lua数据类型&quot;">​</a></h2><p>Lua有8个数据类型</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">nil(空，无效值)</span></span>
<span class="line"><span style="color:#A6ACCD;">boolean(布尔，true/false)</span></span>
<span class="line"><span style="color:#A6ACCD;">number(数值)</span></span>
<span class="line"><span style="color:#A6ACCD;">string(字符串)</span></span>
<span class="line"><span style="color:#A6ACCD;">function(函数)</span></span>
<span class="line"><span style="color:#A6ACCD;">table（表）</span></span>
<span class="line"><span style="color:#A6ACCD;">thread(线程)</span></span>
<span class="line"><span style="color:#A6ACCD;">userdata（用户数据）</span></span></code></pre></div><p>可以使用type函数测试给定变量或者的类型：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">print(type(nil))				--&gt;nil</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(true))               --&gt; boolean</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(1.1*1.1))             --&gt; number</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(&quot;Hello world&quot;))      --&gt; string</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(io.stdin))			--&gt;userdata</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(print))              --&gt; function</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(type))               --&gt;function</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type{})					--&gt;table</span></span>
<span class="line"><span style="color:#A6ACCD;">print(type(type(X)))            --&gt; string</span></span></code></pre></div><h3 id="nil" tabindex="-1">nil <a class="header-anchor" href="#nil" aria-label="Permalink to &quot;nil&quot;">​</a></h3><p>nil是一种只有一个nil值的类型，它的作用可以用来与其他所有值进行区分，也可以当想要移除一个变量时，只需要将该变量名赋值为nil,垃圾回收就会会释放该变量所占用的内存。</p><h3 id="boolean" tabindex="-1">boolean <a class="header-anchor" href="#boolean" aria-label="Permalink to &quot;boolean&quot;">​</a></h3><p>boolean类型具有两个值，true和false。boolean类型一般被用来做条件判断的真与假。在Lua语言中，只会将false和nil视为假，其他的都视为真，特别是在条件检测中0和空字符串都会认为是真，这个和我们熟悉的大多数语言不太一样。</p><h3 id="number" tabindex="-1">number <a class="header-anchor" href="#number" aria-label="Permalink to &quot;number&quot;">​</a></h3><p>在Lua5.3版本开始，Lua语言为数值格式提供了两种选择:integer(整型)和float(双精度浮点型)[和其他语言不太一样，float不代表单精度类型]。</p><p>数值常量的表示方式:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&gt;4			--&gt;4</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;0.4		--&gt;0.4</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;4.75e-3	--&gt;0.00475</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;4.75e3		--&gt;4750</span></span></code></pre></div><p>不管是整型还是双精度浮点型，使用type()函数来取其类型，都会返回的是number</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&gt;type(3)	--&gt;number</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;type(3.3)	--&gt;number</span></span></code></pre></div><p>所以它们之间是可以相互转换的，同时，具有相同算术值的整型值和浮点型值在Lua语言中是相等的</p><h3 id="string" tabindex="-1">string <a class="header-anchor" href="#string" aria-label="Permalink to &quot;string&quot;">​</a></h3><p>Lua语言中的字符串即可以表示单个字符，也可以表示一整本书籍。在Lua语言中，操作100K或者1M个字母组成的字符串的程序很常见。</p><p>可以使用单引号或双引号来声明字符串</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&gt;a = &quot;hello&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;b = &#39;world&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;print(a)	--&gt;hello</span></span>
<span class="line"><span style="color:#A6ACCD;">&gt;print(b) 	--&gt;world</span></span></code></pre></div><p>如果声明的字符串比较长或者有多行，则可以使用如下方式进行声明</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">html = [[</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;html&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;head&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;title&gt;Lua-string&lt;/title&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;/head&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;body&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;a href=&quot;http://www.lua.org&quot;&gt;Lua&lt;/a&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;/body&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;/html&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">]]</span></span></code></pre></div><h3 id="table-⭐" tabindex="-1">table ⭐ <a class="header-anchor" href="#table-⭐" aria-label="Permalink to &quot;table ⭐&quot;">​</a></h3><blockquote><p>table是Lua语言中最主要和强大的数据结构。使用表， Lua 语言可以以一种简单、统一且高效的方式表示数组、集合、记录和其他很多数据结构。 Lua语言中的表本质上是一种辅助数组。这种数组比Java中的数组更加灵活，可以使用数值做索引，也可以使用字符串或其他任意类型的值作索引(除nil外)。</p></blockquote><p>创建表的最简单方式:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&gt; a = {}</span></span></code></pre></div><p>创建数组:我们都知道数组就是相同数据类型的元素按照一定顺序排列的集合，那么使用table如何创建一个数组呢?</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&gt;arr = {&quot;TOM&quot;,&quot;JERRY&quot;,&quot;ROSE&quot;}</span></span></code></pre></div><p>要想获取数组中的值，我们可以通过如下内容来获取:</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">-- 下标默认从1开始</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">])		</span><span style="color:#89DDFF;">nil</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">])		TOM</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">])		JERRY</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">])		ROSE</span></span></code></pre></div><p>​ 从上面的结果可以看出来，数组的下标默认是从1开始的。所以上述创建数组，也可以通过如下方式来创建</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> {}</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOM</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr[</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JERRY</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr[</span><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">ROSE</span><span style="color:#89DDFF;">&quot;</span></span></code></pre></div><p>上面我们说过了，表的索引即可以是数字，也可以是字符串等其他的内容，所以我们也可以将索引更改为字符串来创建</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> {}</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">X</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">10</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Y</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">20</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Z</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">30</span></span></code></pre></div><p>当然，如果想要获取这些数组中的值，可以使用下面的方式</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">-- 方式一</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">X</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">])</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Y</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">])</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Z</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">])</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 方式二</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr.</span><span style="color:#FFCB6B;">X</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr.</span><span style="color:#FFCB6B;">Y</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(arr.</span><span style="color:#FFCB6B;">Z</span><span style="color:#A6ACCD;">)</span></span></code></pre></div><p>当前table的灵活不进于此，还有更灵活的声明方式</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">arr </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> {</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOM</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,X</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">10</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JERRY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,Y</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">20</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">ROSE</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,Z</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">30</span><span style="color:#A6ACCD;">}</span></span></code></pre></div><p>如何获取上面的值?</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#FFCB6B;">TOM</span><span style="color:#A6ACCD;"> :  arr[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">]</span></span>
<span class="line"><span style="color:#F78C6C;">10</span><span style="color:#A6ACCD;">  :  arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">X</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">] | arr.</span><span style="color:#FFCB6B;">X</span></span>
<span class="line"><span style="color:#FFCB6B;">JERRY</span><span style="color:#A6ACCD;">: arr[</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">]</span></span>
<span class="line"><span style="color:#F78C6C;">20</span><span style="color:#A6ACCD;">  :  arr[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Y</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">] | arr.</span><span style="color:#FFCB6B;">Y</span></span>
<span class="line"><span style="color:#A6ACCD;">ROESE?</span></span></code></pre></div><h3 id="thread" tabindex="-1">thread <a class="header-anchor" href="#thread" aria-label="Permalink to &quot;thread&quot;">​</a></h3><blockquote><p>thread翻译过来是线程的意思，在Lua中，thread用来表示执行的独立线路，用来执行协同程序。</p></blockquote><h3 id="userdata" tabindex="-1">userdata <a class="header-anchor" href="#userdata" aria-label="Permalink to &quot;userdata&quot;">​</a></h3><blockquote><p>userdata是一种用户自定义数据，用于表示一种由应用程序或C/C++语言库所创建的类型。</p></blockquote><h2 id="function-函数-⭐" tabindex="-1">function 函数 ⭐ <a class="header-anchor" href="#function-函数-⭐" aria-label="Permalink to &quot;function 函数 ⭐&quot;">​</a></h2><p>在 Lua语言中，函数（ Function ）是对语句和表达式进行抽象的主要方式。</p><h3 id="定义函数语法" tabindex="-1">定义函数语法 <a class="header-anchor" href="#定义函数语法" aria-label="Permalink to &quot;定义函数语法&quot;">​</a></h3><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">functionName</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">params</span><span style="color:#89DDFF;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><h3 id="传参" tabindex="-1">传参 <a class="header-anchor" href="#传参" aria-label="Permalink to &quot;传参&quot;">​</a></h3><blockquote><p>函数被调用的时候，传入的参数个数与定义函数时使用的参数个数不一致的时候，Lua 语言会通过 抛弃多余参数和将不足的参数设为 nil 的方式来调整参数的个数。</p></blockquote><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">f</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">a</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;font-style:italic;">b</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(a,b)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"></span>
<span class="line"><span style="color:#82AAFF;">f</span><span style="color:#A6ACCD;">()		</span><span style="color:#676E95;font-style:italic;">--&gt; nil  nil</span></span>
<span class="line"><span style="color:#82AAFF;">f</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">)	</span><span style="color:#676E95;font-style:italic;">--&gt; 2 nil</span></span>
<span class="line"><span style="color:#82AAFF;">f</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">6</span><span style="color:#A6ACCD;">)	</span><span style="color:#676E95;font-style:italic;">--&gt; 2 6</span></span>
<span class="line"><span style="color:#82AAFF;">f</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">2.6</span><span style="color:#A6ACCD;">.8)	</span><span style="color:#676E95;font-style:italic;">--&gt; 2 6 (8被丢弃)</span></span></code></pre></div><h3 id="可变参数" tabindex="-1">可变参数 <a class="header-anchor" href="#可变参数" aria-label="Permalink to &quot;可变参数&quot;">​</a></h3><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">add</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">...)</span></span>
<span class="line"><span style="color:#A6ACCD;">a,b,c</span><span style="color:#89DDFF;">=...</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(a)</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(b)</span></span>
<span class="line"><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(c)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"></span>
<span class="line"><span style="color:#82AAFF;">add</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">)  </span><span style="color:#676E95;font-style:italic;">--&gt; 1 2 3</span></span></code></pre></div><h3 id="多个返回值" tabindex="-1">多个返回值 <a class="header-anchor" href="#多个返回值" aria-label="Permalink to &quot;多个返回值&quot;">​</a></h3><p>函数返回值可以有多个，这点和Java不太一样</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">f</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">a</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;font-style:italic;">b</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> a,b</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">x,y</span><span style="color:#89DDFF;">=</span><span style="color:#82AAFF;">f</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">11</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">22</span><span style="color:#A6ACCD;">)	</span><span style="color:#676E95;font-style:italic;">--&gt; x=11,y=22</span></span></code></pre></div><h2 id="lua控制结构" tabindex="-1">Lua控制结构 <a class="header-anchor" href="#lua控制结构" aria-label="Permalink to &quot;Lua控制结构&quot;">​</a></h2><p>Lua 语言提供了一组精简且常用的控制结构，包括用于条件执行的证 以及用于循环的 while、 repeat 和 for。 所有的控制结构语法上都有一个显式的终结符： end 用于终结 if、 for 及 while 结构， until 用于终结 repeat 结构。</p><h3 id="if-then-elseif-else" tabindex="-1">if then elseif else <a class="header-anchor" href="#if-then-elseif-else" aria-label="Permalink to &quot;if then elseif else&quot;">​</a></h3><p>if语句先测试其条件，并根据条件是否满足执行相应的 then 部分或 else 部分。 else 部分 是可选的。</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">testif</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">a</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">&gt;</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;"> 	</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a是正数</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">testif</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">a</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">&gt;</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;"> 	</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a是正数</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">else</span></span>
<span class="line"><span style="color:#A6ACCD;"> 	</span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a是负数</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>如果要编写嵌套的 if 语句，可以使用 elseif。 它类似于在 else 后面紧跟一个if。根据传入的年龄返回不同的结果，如</p><blockquote><p>age&lt;=18 青少年，age&gt;18 , age &lt;=45 青年，age&gt;45 , age&lt;=60 中年人，age&gt;60 老年人</p></blockquote><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">show</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">age</span><span style="color:#89DDFF;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">&lt;=</span><span style="color:#F78C6C;">18</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;">       </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">青少年</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;font-style:italic;">elseif</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">&gt;</span><span style="color:#F78C6C;">18</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">and</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">&lt;=</span><span style="color:#F78C6C;">45</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;">       </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">青年</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;font-style:italic;">elseif</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">&gt;</span><span style="color:#F78C6C;">45</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">and</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">&lt;=</span><span style="color:#F78C6C;">60</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;">       </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">中年人</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;font-style:italic;">elseif</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">&gt;</span><span style="color:#F78C6C;">60</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;">       </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">老年人</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><h3 id="while循环" tabindex="-1">while循环 <a class="header-anchor" href="#while循环" aria-label="Permalink to &quot;while循环&quot;">​</a></h3><p>顾名思义，当条件为真时 while 循环会重复执行其循环体。 Lua 语言先测试 while 语句 的条件，若条件为假则循环结束；否则， Lua 会执行循环体并不断地重复这个过程。</p><p>语法：</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">while</span><span style="color:#A6ACCD;"> 条件 </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;">  循环体</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>例子:实现数组的循环</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">testWhile</span><span style="color:#89DDFF;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;font-style:italic;">while</span><span style="color:#A6ACCD;"> i</span><span style="color:#89DDFF;">&lt;=</span><span style="color:#F78C6C;">10</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(i)</span></span>
<span class="line"><span style="color:#A6ACCD;">      i</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">i</span><span style="color:#89DDFF;">+</span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><h3 id="repeat循环" tabindex="-1">repeat循环 <a class="header-anchor" href="#repeat循环" aria-label="Permalink to &quot;repeat循环&quot;">​</a></h3><p>顾名思义， repeat-until语句会重复执行其循环体直到条件为真时结束。 由于条件测试在循环体之后执行，所以循环体至少会执行一次。</p><p>语法</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">repeat</span></span>
<span class="line"><span style="color:#A6ACCD;"> 循环体</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">until</span><span style="color:#A6ACCD;"> 条件</span></span></code></pre></div><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">testRepeat</span><span style="color:#89DDFF;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">10</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;font-style:italic;">repeat</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(i)</span></span>
<span class="line"><span style="color:#A6ACCD;">      i</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">i</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;font-style:italic;">until</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">&lt;</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><h3 id="for循环-⭐" tabindex="-1">for循环 ⭐ <a class="header-anchor" href="#for循环-⭐" aria-label="Permalink to &quot;for循环 ⭐&quot;">​</a></h3><p>数值型for循环</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> param</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">exp1,exp2,exp3 </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;"> 循环体</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>param的值从exp1变化到exp2之前的每次循环会执行 循环体，并在每次循环结束后将步长(step)exp3增加到param上。exp3可选，如果不设置默认为1</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> i </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">100</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">10</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(i)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>泛型for循环</p><p>泛型for循环通过一个迭代器函数来遍历所有值，类似于java中的foreach语句。</p><p>语法</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> i,v </span><span style="color:#89DDFF;font-style:italic;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">ipairs</span><span style="color:#A6ACCD;">(x) </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;">	循环体</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>i是数组索引值，v是对应索引的数组元素值，ipairs是Lua提供的一个迭代器函数，用来迭代数组，x是要遍历的数组。</p><p>例如:</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">arr </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> {</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOME</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JERRY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">ROWS</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">LUCY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">}</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> i,v </span><span style="color:#89DDFF;font-style:italic;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">ipairs</span><span style="color:#A6ACCD;">(arr) </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(i,v)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>上述实例输出的结果为</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">	TOM</span></span>
<span class="line"><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">	JERRY</span></span>
<span class="line"><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">	ROWS</span></span>
<span class="line"><span style="color:#F78C6C;">4</span><span style="color:#A6ACCD;">	LUCY</span></span></code></pre></div><p>但是如果将arr的值进行修改为</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">arr </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> {</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOME</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JERRY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">ROWS</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,x</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JACK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">LUCY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">}</span></span></code></pre></div><p>同样的代码在执行的时候，就只能看到和之前一样的结果，而其中的x为JACK就无法遍历出来，缺失了数据，如果解决呢?</p><p>我们可以将迭代器函数变成pairs,如</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> i,v </span><span style="color:#89DDFF;font-style:italic;">in</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">pairs</span><span style="color:#A6ACCD;">(arr) </span><span style="color:#89DDFF;font-style:italic;">do</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">print</span><span style="color:#A6ACCD;">(i,v)</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">end</span></span></code></pre></div><p>上述实例就输出的结果为</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">	TOM</span></span>
<span class="line"><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">	JERRY</span></span>
<span class="line"><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">	ROWS</span></span>
<span class="line"><span style="color:#F78C6C;">4</span><span style="color:#A6ACCD;">	LUCY</span></span>
<span class="line"><span style="color:#A6ACCD;">x	JACK</span></span></code></pre></div><h1 id="openrestry" tabindex="-1">OpenRestry <a class="header-anchor" href="#openrestry" aria-label="Permalink to &quot;OpenRestry&quot;">​</a></h1><h2 id="概念-1" tabindex="-1">概念 <a class="header-anchor" href="#概念-1" aria-label="Permalink to &quot;概念&quot;">​</a></h2><blockquote><p>淘宝开发的ngx_lua模块通过将lua解释器集成进Nginx，可以采用lua脚本实现业务逻辑，由于lua的紧凑、快速以及内建协程，所以在保证高并发服务能力的同时极大地降低了业务逻辑实现成本。</p></blockquote><blockquote><p>前面我们提到过，OpenResty是由淘宝工程师开发的，所以其官方网站(<a href="http://openresty.org/" target="_blank" rel="noreferrer">http://openresty.org/</a>)我们读起来是非常的方便。OpenResty是一个基于Nginx与 Lua 的高性能 Web 平台，其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。所以本身OpenResty内部就已经集成了Nginx和Lua，所以我们使用起来会更加方便。</p></blockquote><h2 id="环境准备" tabindex="-1">环境准备 <a class="header-anchor" href="#环境准备" aria-label="Permalink to &quot;环境准备&quot;">​</a></h2><h3 id="安装编译" tabindex="-1">安装编译 <a class="header-anchor" href="#安装编译" aria-label="Permalink to &quot;安装编译&quot;">​</a></h3><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;"># 使用wget下载</span></span>
<span class="line"><span style="color:#FFCB6B;">wget</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">https://openresty.org/download/openresty-1.15.8.2.tar.gz</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"># 解压缩</span></span>
<span class="line"><span style="color:#FFCB6B;">tar</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">-zxvf</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">openresty-1.15.8.2.tar.gz</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"># 进入OpenResty目录:</span></span>
<span class="line"><span style="color:#82AAFF;">cd</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">openresty-1.15.8.2</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"># 编译安装</span></span>
<span class="line"><span style="color:#FFCB6B;">./configure</span></span>
<span class="line"><span style="color:#FFCB6B;">make</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">make</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">install</span></span></code></pre></div><h3 id="访问测试" tabindex="-1">访问测试 <a class="header-anchor" href="#访问测试" aria-label="Permalink to &quot;访问测试&quot;">​</a></h3><p>进入OpenResty的目录，找到nginx：cd /usr/local/openresty/nginx/，在conf目录下的nginx.conf添加如下内容</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">lua</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">ngx.say(&quot;&lt;h1&gt;HELLO,OpenRestry&lt;/h1&gt;&quot;)</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>在sbin目录下启动nginx</p><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#82AAFF;">cd</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">sbin</span></span>
<span class="line"><span style="color:#FFCB6B;">./nginx</span></span></code></pre></div><p>通过浏览器访问测试</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301191044533.png" alt="image-20230119104449454" style="zoom:67%;"><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301191045831.png" alt="image-20230119104518775" style="zoom:80%;"><h2 id="ngx-lua-详解" tabindex="-1">ngx_lua 详解 <a class="header-anchor" href="#ngx-lua-详解" aria-label="Permalink to &quot;ngx_lua 详解&quot;">​</a></h2><p>使用Lua编写Nginx脚本的基本构建块是指令。指令用于指定何时运行用户Lua代码以及如何使用结果。下图显示了执行指令的顺序。</p><p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022/202204301712574.png" alt="1604717983815"></p><p>先来解释下*的作用</p><div class="language-scala"><button title="Copy Code" class="copy"></button><span class="lang">scala</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;">：无 ， 即 xxx_by_lua ,指令后面跟的是 lua指令</span></span>
<span class="line"><span style="color:#89DDFF;">*:</span><span style="color:#A6ACCD;">_file，即 xxx_by_lua_file 指令后面跟的是 lua文件</span></span>
<span class="line"><span style="color:#89DDFF;">*:</span><span style="color:#A6ACCD;">_block,即 xxx_by_lua_block 在0</span><span style="color:#F78C6C;">.9</span><span style="color:#A6ACCD;">.17版后替换init_by_lua_file</span></span></code></pre></div><h3 id="init-by-lua" tabindex="-1">init_by_lua* <a class="header-anchor" href="#init-by-lua" aria-label="Permalink to &quot;init_by_lua*&quot;">​</a></h3><blockquote><p>该指令在每次Nginx重新加载配置时执行，可以用来完成一些耗时模块的加载，或者初始化一些全局配置。</p></blockquote><h3 id="init-worker-by-lua" tabindex="-1">init_worker_by_lua* <a class="header-anchor" href="#init-worker-by-lua" aria-label="Permalink to &quot;init_worker_by_lua*&quot;">​</a></h3><blockquote><p>该指令用于启动一些定时任务，如心跳检查、定时拉取服务器配置等。</p></blockquote><h3 id="set-by-lua" tabindex="-1">set_by_lua* <a class="header-anchor" href="#set-by-lua" aria-label="Permalink to &quot;set_by_lua*&quot;">​</a></h3><blockquote><p>该指令只要用来做变量赋值，这个指令一次只能返回一个值，并将结果赋值给Nginx中指定的变量。</p></blockquote><h3 id="rewrite-by-lua" tabindex="-1">rewrite_by_lua* <a class="header-anchor" href="#rewrite-by-lua" aria-label="Permalink to &quot;rewrite_by_lua*&quot;">​</a></h3><blockquote><p>该指令用于执行内部URL重写或者外部重定向，典型的如伪静态化URL重写，本阶段在rewrite处理阶段的最后默认执行。</p></blockquote><h3 id="access-by-lua" tabindex="-1">access_by_lua* <a class="header-anchor" href="#access-by-lua" aria-label="Permalink to &quot;access_by_lua*&quot;">​</a></h3><blockquote><p>该指令用于访问控制。例如，如果只允许内网IP访问。</p></blockquote><h3 id="content-by-lua" tabindex="-1">content_by_lua* <a class="header-anchor" href="#content-by-lua" aria-label="Permalink to &quot;content_by_lua*&quot;">​</a></h3><blockquote><p>该指令是应用最多的指令，大部分任务是在这个阶段完成的，其他的过程往往为这个阶段准备数据，正式处理基本都在本阶段。</p></blockquote><h3 id="header-filter-by-lua" tabindex="-1">header_filter_by_lua* <a class="header-anchor" href="#header-filter-by-lua" aria-label="Permalink to &quot;header_filter_by_lua*&quot;">​</a></h3><blockquote><p>该指令用于设置应答消息的头部信息。</p></blockquote><h3 id="body-filter-by-lua" tabindex="-1">body_filter_by_lua* <a class="header-anchor" href="#body-filter-by-lua" aria-label="Permalink to &quot;body_filter_by_lua*&quot;">​</a></h3><blockquote><p>该指令是对响应数据进行过滤，如截断、替换。</p></blockquote><h3 id="log-by-lua" tabindex="-1">log_by_lua* <a class="header-anchor" href="#log-by-lua" aria-label="Permalink to &quot;log_by_lua*&quot;">​</a></h3><blockquote><p>该指令用于在log请求处理阶段，用Lua代码处理日志，但并不替换原有log处理。</p></blockquote><h3 id="balancer-by-lua" tabindex="-1">balancer_by_lua* <a class="header-anchor" href="#balancer-by-lua" aria-label="Permalink to &quot;balancer_by_lua*&quot;">​</a></h3><blockquote><p>该指令主要的作用是用来实现上游服务器的负载均衡器算法</p></blockquote><h3 id="ssl-certificate-by" tabindex="-1">ssl_certificate_by_* <a class="header-anchor" href="#ssl-certificate-by" aria-label="Permalink to &quot;ssl_certificate_by_*&quot;">​</a></h3><blockquote><p>该指令作用在Nginx和下游服务开始一个SSL握手操作时将允许本配置项的Lua代码。</p></blockquote><h2 id="ngx-lua-案例⭐" tabindex="-1">ngx_lua 案例⭐ <a class="header-anchor" href="#ngx-lua-案例⭐" aria-label="Permalink to &quot;ngx_lua 案例⭐&quot;">​</a></h2><h3 id="需求描述" tabindex="-1">需求描述 <a class="header-anchor" href="#需求描述" aria-label="Permalink to &quot;需求描述&quot;">​</a></h3><blockquote><p><a href="http://192.168.22.130?name=%E5%BC%A0%E4%B8%89&amp;gender=1" target="_blank" rel="noreferrer">http://192.168.22.130?name=张三&amp;gender=1</a></p></blockquote><blockquote><p>Nginx接收到请求后，根据gender传入的值，</p><p>如果gender传入的是1，则在页面上展示张三先生</p><p>如果gender传入的是0，则在页面上展示张三女士</p><p>如果未传或者传入的不是1和2则在页面上展示张三</p></blockquote><h3 id="实现代码" tabindex="-1">实现代码 <a class="header-anchor" href="#实现代码" aria-label="Permalink to &quot;实现代码&quot;">​</a></h3><blockquote><p>注意：要把注释去掉才能执行成功</p></blockquote><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#82AAFF;">getByGender</span><span style="color:#A6ACCD;"> {</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#82AAFF;">default_type</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">	set_by_lua $</span><span style="color:#82AAFF;">name</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">		</span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> uri_args </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> ngx.</span><span style="color:#FFCB6B;">req</span><span style="color:#A6ACCD;">.</span><span style="color:#82AAFF;">get_uri_args</span><span style="color:#A6ACCD;">() </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 获取传入参数</span></span>
<span class="line"><span style="color:#A6ACCD;">		gender </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> uri_args[</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">gender</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">] </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 将传入参数进行赋值</span></span>
<span class="line"><span style="color:#A6ACCD;">		name </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> uri_args[</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">name</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">]</span></span>
<span class="line"><span style="color:#A6ACCD;">		</span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> gender</span><span style="color:#89DDFF;">==</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">1</span><span style="color:#89DDFF;">&#39; </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;">			</span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> name</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">先生</span><span style="color:#89DDFF;">&#39; </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">表示拼接字符串，因为外部使用双引号，此处必须单引号</span></span>
<span class="line"><span style="color:#A6ACCD;">		</span><span style="color:#89DDFF;font-style:italic;">elseif</span><span style="color:#A6ACCD;"> gender</span><span style="color:#89DDFF;">==</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">0</span><span style="color:#89DDFF;">&#39; </span><span style="color:#89DDFF;font-style:italic;">then</span></span>
<span class="line"><span style="color:#A6ACCD;">			</span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> name</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">女士</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">		</span><span style="color:#89DDFF;font-style:italic;">else</span></span>
<span class="line"><span style="color:#A6ACCD;">			</span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> name</span></span>
<span class="line"><span style="color:#A6ACCD;">		</span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">	charset utf</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">8</span><span style="color:#A6ACCD;">; </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 避免乱码</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#82AAFF;">header_filter_by_lua</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">		ngx.</span><span style="color:#FFCB6B;">header</span><span style="color:#A6ACCD;">.</span><span style="color:#FFCB6B;">aaa</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">bbb</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">200</span><span style="color:#A6ACCD;"> $name;</span></span>
<span class="line"><span style="color:#A6ACCD;">}</span></span></code></pre></div><p>访问测试</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">./</span><span style="color:#A6ACCD;">nginx </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">s reload</span></span></code></pre></div><p><a href="http://192.168.22.130/getByGender?name=%E5%BC%A0%E4%B8%89&amp;gender=1" target="_blank" rel="noreferrer">http://192.168.22.130/getByGender?name=张三&amp;gender=1</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202211457.png" alt="image-20220620221157375" style="zoom:67%;"><h2 id="操作redis" tabindex="-1">操作Redis <a class="header-anchor" href="#操作redis" aria-label="Permalink to &quot;操作Redis&quot;">​</a></h2><blockquote><p>Redis在系统中经常作为数据缓存、内存数据库使用，在大型系统中扮演着非常重要的作用。在Nginx核心系统中，Redis是常备组件。Nginx支持3种方法访问Redis,分别是HttpRedis模块、HttpRedis2Module、lua-resty-redis库。</p></blockquote><blockquote><p>HttpRedis模块提供的指令少，功能单一，适合做简单缓存</p><p>HttpRedis2Module模块比HttpRedis模块操作更灵活，功能更强大。</p><p>Lua-resty-redis库是OpenResty提供的一个操作Redis的接口库，可根据自己的业务情况做一些逻辑处理，适合做复杂的业务逻辑。所以本次课程将主要以Lua-resty-redis来进行讲解</p></blockquote><h3 id="resty-redis-api" tabindex="-1">resty-redis API <a class="header-anchor" href="#resty-redis-api" aria-label="Permalink to &quot;resty-redis API&quot;">​</a></h3><blockquote><ul><li>lua-resty-redis提供了访问Redis的详细API，包括创建对接、连接、操作、数据处理等。基本与Redis的操作对应</li><li>redis = require &quot;resty.redis&quot;</li><li>new语法: redis,err = redis:new(),创建一个Redis对象。</li><li>connect语法: ok,err=redis:connect(host,port[,options_table]),设置连接Redis的连接信息。ok:连接成功返回 1，连接失败返回nil，err:返回对应的错误信息</li><li>set_timeout语法: redis:set_timeout(time) ，设置请求操作Redis的超时时间。</li><li>close语法: ok,err = redis:close(),关闭当前连接，成功返回1，失败返回nil和错误信息</li><li>redis命令对应的方法：在lua-resty-redis中，所有的Redis命令都有自己的方法，方法名字和命令名字相同，只是全部为小写</li></ul></blockquote><h3 id="环境准备-1" tabindex="-1">环境准备 <a class="header-anchor" href="#环境准备-1" aria-label="Permalink to &quot;环境准备&quot;">​</a></h3><p>步骤一:准备一个Redis环境</p><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;"># 连接地址</span></span>
<span class="line"><span style="color:#A6ACCD;">host</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">192.168.0.130</span></span>
<span class="line"><span style="color:#A6ACCD;">port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">6379</span></span>
<span class="line"><span style="color:#FFCB6B;">redis-server</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">/etc/redis.conf</span></span>
<span class="line"><span style="color:#FFCB6B;">redis-cli</span></span></code></pre></div><h3 id="实现代码-1" tabindex="-1">实现代码 <a class="header-anchor" href="#实现代码-1" aria-label="Permalink to &quot;实现代码&quot;">​</a></h3><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#82AAFF;">testRedis</span><span style="color:#A6ACCD;"> {</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">default_type</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">content_by_lua_block</span><span style="color:#A6ACCD;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> redis </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.redis</span><span style="color:#89DDFF;">&quot; </span><span style="color:#676E95;font-style:italic;">-- 引入Redis</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> redisObj </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">redis</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">new</span><span style="color:#A6ACCD;">()  </span><span style="color:#676E95;font-style:italic;">--创建Redis对象</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">redisObj</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">set_timeout</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">--设置超时数据为1s</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> ok,err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">redisObj</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">connect</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#F78C6C;">6379</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">--设置redis连接信息</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">not</span><span style="color:#A6ACCD;"> ok </span><span style="color:#89DDFF;font-style:italic;">then</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">--判断是否连接成功</span></span>
<span class="line"><span style="color:#A6ACCD;">           ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">failed to connection redis</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,err)</span></span>
<span class="line"><span style="color:#A6ACCD;">           </span><span style="color:#89DDFF;font-style:italic;">return</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#A6ACCD;">        ok,err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">redisObj</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">set</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">username</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOM</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span><span style="color:#676E95;font-style:italic;">--存入数据</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">not</span><span style="color:#A6ACCD;"> ok </span><span style="color:#89DDFF;font-style:italic;">then</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">--判断是否存入成功</span></span>
<span class="line"><span style="color:#A6ACCD;">           ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">failed to set username</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,err)</span></span>
<span class="line"><span style="color:#A6ACCD;">           </span><span style="color:#89DDFF;font-style:italic;">return</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> res,err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">redisObj</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">get</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">username</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">--从redis中获取数据</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(res)	</span><span style="color:#676E95;font-style:italic;">--将数据写会消息体中，返回给前端页面</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">redisObj</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">close</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">    }</span></span>
<span class="line"><span style="color:#A6ACCD;">}</span></span></code></pre></div><p>步骤四:运行测试效果</p><p><a href="http://192.168.22.130/testRedis" target="_blank" rel="noreferrer">http://192.168.22.130/testRedis</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202218930.png" alt="image-20220620221800877" style="zoom:67%;"><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202218074.png" alt="image-20220620221843012" style="zoom:67%;"><h2 id="操作mysql" tabindex="-1">操作MySQL <a class="header-anchor" href="#操作mysql" aria-label="Permalink to &quot;操作MySQL&quot;">​</a></h2><p>MySQL是一个使用广泛的关系型数据库。在ngx_lua中，MySQL有两种访问模式,分别是使</p><blockquote><p>用ngx_lua模块和lua-resty-mysql模块：这两个模块是安装OpenResty时默认安装的。</p><p>使用drizzle_nginx_module(HttpDrizzleModule)模块：需要单独安装，这个库现不在OpenResty中。</p></blockquote><blockquote><p>lua-resty-mysql是OpenResty开发的模块，使用灵活、功能强大，适合复杂的业务场景，同时支持存储过程的访问</p></blockquote><h3 id="mysql-连接和数据" tabindex="-1">MySQL 连接和数据 <a class="header-anchor" href="#mysql-连接和数据" aria-label="Permalink to &quot;MySQL 连接和数据&quot;">​</a></h3><p>创建一个数据库表及表中的数据。</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">mysql </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">uroot </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">p123456</span></span>
<span class="line"><span style="color:#A6ACCD;">mysql </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">uroot </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">p123456 </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">h </span><span style="color:#F78C6C;">192.168.0.199</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">P </span><span style="color:#F78C6C;">3307</span></span></code></pre></div><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">create database nginx_db</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">use nginx_db</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">create table users</span><span style="color:#89DDFF;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">   id int primary key auto_increment</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">   username varchar(</span><span style="color:#F78C6C;">30</span><span style="color:#89DDFF;">),</span></span>
<span class="line"><span style="color:#A6ACCD;">   birthday date</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">   salary double</span></span>
<span class="line"><span style="color:#89DDFF;">)</span><span style="color:#FFCB6B;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">insert into users</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">birthday</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">salary</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> values</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">null</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOM</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1988-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">10000.0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">insert into users</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">birthday</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">salary</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> values</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">null</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JERRY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1989-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">20000.0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">insert into users</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">birthday</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">salary</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> values</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">null</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">ROWS</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1990-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">30000.0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">insert into users</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">birthday</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">salary</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> values</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">null</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">LUCY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1991-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">40000.0</span><span style="color:#89DDFF;">);</span></span>
<span class="line"><span style="color:#A6ACCD;">insert into users</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">birthday</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">salary</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> values</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">null</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JACK</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1992-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">50000.0</span><span style="color:#89DDFF;">);</span></span></code></pre></div><h3 id="resty-mysql-api" tabindex="-1">resty-mysql API <a class="header-anchor" href="#resty-mysql-api" aria-label="Permalink to &quot;resty-mysql API&quot;">​</a></h3><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">-- 引入&quot;resty.mysql&quot;模块</span></span>
<span class="line"><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- new，创建一个MySQL连接对象，遇到错误时，db为nil，err为错误描述信息</span></span>
<span class="line"><span style="color:#A6ACCD;">db,err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mysql</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">new</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- connect：尝试连接到一个MySQL服务器</span></span>
<span class="line"><span style="color:#A6ACCD;">ok,err</span><span style="color:#89DDFF;">=</span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">connect</span><span style="color:#A6ACCD;">(options)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- options是一个参数的Lua表结构，里面包含数据库连接的相关信息</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">host</span><span style="color:#A6ACCD;">:服务器主机名或IP地址</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">port</span><span style="color:#A6ACCD;">:服务器监听端口，默认为3306</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">user</span><span style="color:#A6ACCD;">:登录的用户名</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">password</span><span style="color:#A6ACCD;">:登录密码</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#FFCB6B;">database</span><span style="color:#A6ACCD;">:使用的数据库名</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- set_timeout 设置子请求的超时时间(ms)，包括connect方法</span></span>
<span class="line"><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">set_timeout</span><span style="color:#A6ACCD;">(time)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- close 关闭当前MySQL连接并返回状态。如果成功，则返回1；如果出现任何错误，则将返回nil和错误描述。</span></span>
<span class="line"><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">close</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- send_query：异步向远程MySQL发送一个查询。如果成功则返回成功发送的字节数；如果错误，则返回nil和错误描述</span></span>
<span class="line"><span style="color:#A6ACCD;">bytes,err</span><span style="color:#89DDFF;">=</span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">send_query</span><span style="color:#A6ACCD;">(sql)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- read_result：从MySQL服务器返回结果中读取一行数据。res返回一个描述OK包或结果集包的Lua表</span></span>
<span class="line"><span style="color:#A6ACCD;">res, err, errcode, sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">read_result</span><span style="color:#A6ACCD;">() </span></span>
<span class="line"><span style="color:#A6ACCD;">res, err, errcode, sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">read_result</span><span style="color:#A6ACCD;">(rows) </span><span style="color:#676E95;font-style:italic;">--:rows指定返回结果集的最大值，默认为4</span></span></code></pre></div><p>结果集分析</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">-- 如果是查询，则返回一个容纳多行的数组。每行是一个数据列的key-value对，如</span></span>
<span class="line"><span style="color:#A6ACCD;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  {id</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">,username</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">TOM</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,birthday</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1988-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,salary</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">10000.0</span><span style="color:#A6ACCD;">},</span></span>
<span class="line"><span style="color:#A6ACCD;">  {id</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">,username</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">JERRY</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,birthday</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">1989-11-11</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,salary</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">20000.0</span><span style="color:#A6ACCD;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">}</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 如果是增删改，则返回类上如下数据</span></span>
<span class="line"><span style="color:#A6ACCD;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">	insert_id </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">	server_status</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">	warning_count</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">	affected_rows</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">	message</span><span style="color:#89DDFF;">=nil</span></span>
<span class="line"><span style="color:#A6ACCD;">}</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 返回值:</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#FFCB6B;">res</span><span style="color:#A6ACCD;">:操作的结果集</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#FFCB6B;">err</span><span style="color:#A6ACCD;">:错误信息</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#FFCB6B;">errcode</span><span style="color:#A6ACCD;">:MySQL的错误码，比如1064</span></span>
<span class="line"><span style="color:#A6ACCD;">	</span><span style="color:#FFCB6B;">sqlstate</span><span style="color:#A6ACCD;">:返回由5个字符组成的标准SQL错误码，比如42000</span></span></code></pre></div><h3 id="查询实现" tabindex="-1">查询实现 <a class="header-anchor" href="#查询实现" aria-label="Permalink to &quot;查询实现&quot;">​</a></h3><blockquote><p>当连接的是MySQL8时，可能会出现连接不上问题，因此可以进入MySQL8的命令行，执行如下命令即可</p></blockquote><div class="language-mysql"><button title="Copy Code" class="copy"></button><span class="lang">mysql</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">use mysql;</span></span>
<span class="line"><span style="color:#A6ACCD;">update user set plugin=&#39;mysql_native_password&#39; where user=&#39;root&#39;;</span></span>
<span class="line"><span style="color:#A6ACCD;">alter user &#39;root&#39;@&#39;%&#39; identified with mysql_native_password by &#39;123456&#39;;</span></span>
<span class="line"><span style="color:#A6ACCD;">flush privileges;</span></span></code></pre></div><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#82AAFF;">testMySQL</span><span style="color:#A6ACCD;"> {</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">default_type</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    charset utf</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">8</span><span style="color:#A6ACCD;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">content_by_lua_block</span><span style="color:#A6ACCD;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">mysql</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">new</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> ok,err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">connect</span><span style="color:#A6ACCD;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.0.199</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3307</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        }</span></span>
<span class="line"><span style="color:#A6ACCD;">	   </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> err </span><span style="color:#89DDFF;font-style:italic;">then</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">           ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(err)</span></span>
<span class="line"><span style="color:#A6ACCD;">           </span><span style="color:#89DDFF;font-style:italic;">return</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">set_timeout</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">) </span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">send_query</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">select * from users where id = 2</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">local</span><span style="color:#A6ACCD;"> res,err,errcode,sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">read_result</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;"> err </span><span style="color:#89DDFF;font-style:italic;">then</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">           ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(err)</span></span>
<span class="line"><span style="color:#A6ACCD;">           </span><span style="color:#89DDFF;font-style:italic;">return</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;font-style:italic;">end</span></span>
<span class="line"><span style="color:#89DDFF;">        </span><span style="color:#676E95;font-style:italic;">-- 进行结果拼接</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">结果查询成功</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx.</span><span style="color:#82AAFF;">say</span><span style="color:#A6ACCD;">(res[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">].</span><span style="color:#FFCB6B;">id</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">res[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">].</span><span style="color:#FFCB6B;">username</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">res[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">].</span><span style="color:#FFCB6B;">birthday</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">res[</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">].</span><span style="color:#FFCB6B;">salary</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#FFCB6B;">db</span><span style="color:#A6ACCD;">:</span><span style="color:#82AAFF;">close</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">    }</span></span>
<span class="line"><span style="color:#A6ACCD;">}</span></span></code></pre></div><p>进行访问：<a href="http://192.168.22.130/testMySQL" target="_blank" rel="noreferrer">http://192.168.22.130/testMySQL</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.1.30/202301191208846.png" alt="image-20230119120825771" style="zoom:80%;"><h3 id="cjson-结果拼接简化⭐" tabindex="-1">cjson 结果拼接简化⭐ <a class="header-anchor" href="#cjson-结果拼接简化⭐" aria-label="Permalink to &quot;cjson 结果拼接简化⭐&quot;">​</a></h3><p>通过上述的案例学习，read_result()得到的结果res都是table类型，要想在页面上展示，就必须知道table的具体数据结构才能进行遍历获取。处理起来比较麻烦，接下来我们介绍一种简单方式cjson，使用它就可以将table类型的数据转换成json字符串，把json字符串展示在页面上即可。具体如何使用?</p><blockquote><p>1.如何获取返回数据的内容</p><p>2.如何实现查询多条数据</p><p>3.如何实现数据库的增删改操作</p></blockquote><h4 id="cjson用法" tabindex="-1">cjson用法 <a class="header-anchor" href="#cjson用法" aria-label="Permalink to &quot;cjson用法&quot;">​</a></h4><p>步骤一：引入cjson</p><p>方式一：局部变量</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">local cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span></code></pre></div><p>方式二：全局变量，需要设置在server块外部，http块内部</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">init_by_lua_block </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>步骤二：调用cjson的encode方法进行类型转换</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">)</span></span></code></pre></div><h4 id="完整使用" tabindex="-1">完整使用 <a class="header-anchor" href="#完整使用" aria-label="Permalink to &quot;完整使用&quot;">​</a></h4><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">testMySQL </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua_block</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        local mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;"> 定义局部变量</span></span>
<span class="line"><span style="color:#A6ACCD;">        local cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> mysql:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        local ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:connect</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3306</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;"> 批量结果</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">send_query(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">select * from users</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        local res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:read_result()</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;"> cjson的结果</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#A6ACCD;">(res))</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;"> 正常遍历结果</span></span>
<span class="line"><span style="color:#A6ACCD;">        for i</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">v in ipairs(res) do</span></span>
<span class="line"><span style="color:#A6ACCD;">            ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(v</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">v</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">v</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">birthday</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">,</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">v</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">salary)</span></span>
<span class="line"><span style="color:#A6ACCD;">         end</span></span>
<span class="line"><span style="color:#A6ACCD;">    	db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><a href="http://192.168.22.130/testMySQL" target="_blank" rel="noreferrer">http://192.168.22.130/testMySQL</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202238804.png" alt="image-20220620223843739" style="zoom:80%;"><h3 id="增删改实现" tabindex="-1">增删改实现 <a class="header-anchor" href="#增删改实现" aria-label="Permalink to &quot;增删改实现&quot;">​</a></h3><p>优化send_query和read_result</p><p>本方法是send_query和read_result组合的快捷方法。很简单，只要替换SQL就行了</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:query</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">sql[</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">rows]</span><span style="color:#89DDFF;">)</span></span></code></pre></div><p>有了该API，上面的代码我们就可以进行对应的优化，如下:</p><h4 id="查" tabindex="-1">查 <a class="header-anchor" href="#查" aria-label="Permalink to &quot;查&quot;">​</a></h4><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">testMySQL </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua_block</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        local mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> mysql:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        local ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:connect</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3306</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            max_packet_size</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            compact_arrays</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">false</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        local res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:query(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">select * from users</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#A6ACCD;">(res))</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><a href="http://192.168.22.130/testMySQL" target="_blank" rel="noreferrer">http://192.168.22.130/testMySQL</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202246460.png" alt="image-20220620224644360" style="zoom:67%;"><h4 id="增加" tabindex="-1">增加 <a class="header-anchor" href="#增加" aria-label="Permalink to &quot;增加&quot;">​</a></h4><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">testMySQL </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua_block</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        local mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> mysql:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        local ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:connect</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3306</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            max_packet_size</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            compact_arrays</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">false</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        local sql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">insert into users(id,username,birthday,salary)   </span></span>
<span class="line"><span style="color:#A6ACCD;">                     values(null</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">zhangsan</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">2020-11-11</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">32222.0</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:query(sql)</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#A6ACCD;">(res))</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p><a href="http://192.168.22.130/testMySQL" target="_blank" rel="noreferrer">http://192.168.22.130/testMySQL</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202250229.png" alt="image-20220620225029163" style="zoom:67%;"><h4 id="修改" tabindex="-1">修改 <a class="header-anchor" href="#修改" aria-label="Permalink to &quot;修改&quot;">​</a></h4><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">testMySQL </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua_block</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        local mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> mysql:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        local ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:connect</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3306</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            max_packet_size</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            compact_arrays</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">false</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        local sql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">update users set username=&#39;lisi&#39; where id = 6</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:query(sql)</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#A6ACCD;">(res))</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202251049.png" alt="image-20220620225119976" style="zoom:67%;"><h4 id="删除" tabindex="-1">删除 <a class="header-anchor" href="#删除" aria-label="Permalink to &quot;删除&quot;">​</a></h4><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">testMySQL </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua_block</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        local mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> mysql:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        local ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:connect</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">            host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3306</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            max_packet_size</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">1024</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">            compact_arrays</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">false</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        local sql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">delete from users where id = 6</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        local res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">sqlstate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:query(sql)</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#A6ACCD;">(res))</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202253868.png" alt="image-20220620225315803" style="zoom:67%;"><h2 id="综合案例-缓存预热" tabindex="-1">综合案例-缓存预热 <a class="header-anchor" href="#综合案例-缓存预热" aria-label="Permalink to &quot;综合案例-缓存预热&quot;">​</a></h2><blockquote><p>使用ngx_lua模块完成Redis缓存预热</p></blockquote><h3 id="问题分析" tabindex="-1">问题分析 <a class="header-anchor" href="#问题分析" aria-label="Permalink to &quot;问题分析&quot;">​</a></h3><p>（1）先得有一张表(users)，就是上面的users表</p><p>（2）浏览器输入如下地址</p><div class="language-lua"><button title="Copy Code" class="copy"></button><span class="lang">lua</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">-- 存入所有信息</span></span>
<span class="line"><span style="color:#FFCB6B;">http</span><span style="color:#A6ACCD;">:</span><span style="color:#89DDFF;">//</span><span style="color:#F78C6C;">192.168</span><span style="color:#A6ACCD;">.22.130</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">test</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">-- 存入TOM个人信息</span></span>
<span class="line"><span style="color:#FFCB6B;">http</span><span style="color:#A6ACCD;">:</span><span style="color:#89DDFF;">//</span><span style="color:#F78C6C;">192.168</span><span style="color:#A6ACCD;">.22.130</span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">test?username</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">TOM</span></span></code></pre></div><p>（3）从表中查询出符合条件的记录，此时获取的结果为table类型</p><p>（4）使用cjson将table数据转换成json字符串</p><p>（5）将查询的结果数据存入Redis中</p><h3 id="引入资源-全局变量" tabindex="-1">引入资源-全局变量 <a class="header-anchor" href="#引入资源-全局变量" aria-label="Permalink to &quot;引入资源-全局变量&quot;">​</a></h3><p>http块中引入，按照使用顺序依次引入</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">init_by_lua_block </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    mysql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.mysql</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">    redis </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">resty.redis</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">    cjson </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> require </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">cjson</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><p>实现</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">/</span><span style="color:#A6ACCD;">test </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    default_type </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">text/html</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    content_by_lua_block</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">获取请求的参数username</span></span>
<span class="line"><span style="color:#A6ACCD;">        local param </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">req</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">get_uri_args()[</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">username</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">]</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">建立mysql数据库的连接</span></span>
<span class="line"><span style="color:#A6ACCD;">        local db </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> mysql:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        local ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> db:connect</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">                host</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.0.199</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">                port</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">3307</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">                user</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">root</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">                password</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">123456</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">                database</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">nginx_db</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">            </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">        if not ok then</span></span>
<span class="line"><span style="color:#A6ACCD;">            ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">failed connect to mysql:</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err)</span></span>
<span class="line"><span style="color:#A6ACCD;">            return</span></span>
<span class="line"><span style="color:#A6ACCD;">        end</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">设置连接超时时间</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">查询数据</span></span>
<span class="line"><span style="color:#A6ACCD;">        local sql </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;"> 没有传入参数，最上面req</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">get_uri_args获取传入的username</span></span>
<span class="line"><span style="color:#A6ACCD;">        if not param then</span></span>
<span class="line"><span style="color:#A6ACCD;">            sql</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">select * from users</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        else</span></span>
<span class="line"><span style="color:#A6ACCD;">            sql</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">select * from users where username=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">&#39;</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">param</span><span style="color:#89DDFF;">..</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">&#39;</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">        end</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">传递SQL</span></span>
<span class="line"><span style="color:#A6ACCD;">        local res</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">errcode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">sqlstate</span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;">db:query(sql)</span></span>
<span class="line"><span style="color:#A6ACCD;">        if not res then</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">failed to query from mysql:</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err)</span></span>
<span class="line"><span style="color:#A6ACCD;">            return</span></span>
<span class="line"><span style="color:#A6ACCD;">        end</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">连接redis</span></span>
<span class="line"><span style="color:#A6ACCD;">        local rd </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> redis:new()</span></span>
<span class="line"><span style="color:#A6ACCD;">        ok</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> rd:connect(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">192.168.22.130</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F78C6C;">6379</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        if not ok then</span></span>
<span class="line"><span style="color:#A6ACCD;">            ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">failed to connect to redis:</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">err)</span></span>
<span class="line"><span style="color:#A6ACCD;">             return</span></span>
<span class="line"><span style="color:#A6ACCD;">        end</span></span>
<span class="line"><span style="color:#A6ACCD;">        rd</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set_timeout(</span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">--</span><span style="color:#A6ACCD;">循环遍历数据(存入redis)</span></span>
<span class="line"><span style="color:#A6ACCD;">        for i</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">v in ipairs(res) do</span></span>
<span class="line"><span style="color:#A6ACCD;">            rd</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">set(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">user_</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">..</span><span style="color:#A6ACCD;">v</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">username</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> cjson</span><span style="color:#F78C6C;">.encode</span><span style="color:#A6ACCD;">(v))</span></span>
<span class="line"><span style="color:#A6ACCD;">        end</span></span>
<span class="line"><span style="color:#A6ACCD;">        ngx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">say(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">success</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">        rd</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">        db</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">close()</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h3 id="测试" tabindex="-1">测试 <a class="header-anchor" href="#测试" aria-label="Permalink to &quot;测试&quot;">​</a></h3><p><a href="http://192.168.22.130/test?username=TOM" target="_blank" rel="noreferrer">http://192.168.22.130/test?username=TOM</a></p><p><a href="http://192.168.22.130/test" target="_blank" rel="noreferrer">http://192.168.22.130/test</a></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.6.11/202206202318145.png" alt="image-20220620231821073" style="zoom:50%;"><h1 id="性能优化-⭐" tabindex="-1">性能优化 ⭐ <a class="header-anchor" href="#性能优化-⭐" aria-label="Permalink to &quot;性能优化 ⭐&quot;">​</a></h1><p>到这里文章的篇幅较长了，最后再来聊一下关于<code>Nginx</code>的性能优化，主要就简单说说收益最高的几个优化项，在这块就不再展开叙述了，毕竟影响性能都有多方面原因导致的，比如网络、服务器硬件、操作系统、后端服务、程序自身、数据库服务等。</p><h2 id="打开长连接配置" tabindex="-1">打开长连接配置 <a class="header-anchor" href="#打开长连接配置" aria-label="Permalink to &quot;打开长连接配置&quot;">​</a></h2><p>通常Nginx作为代理服务，负责分发客户端的请求，那么建议开启<code>HTTP</code>长连接，用户减少握手的次数，降低服务器损耗，具体如下：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">upstream xxx </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 长连接数</span></span>
<span class="line"><span style="color:#A6ACCD;">    keepalive </span><span style="color:#F78C6C;">32</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 每个长连接提供的最大请求数</span></span>
<span class="line"><span style="color:#A6ACCD;">    keepalived_requests </span><span style="color:#F78C6C;">100</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 每个长连接没有新的请求时，保持的最长时间</span></span>
<span class="line"><span style="color:#A6ACCD;">    keepalive_timeout </span><span style="color:#F78C6C;">60s</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="开启零拷贝技术" tabindex="-1">开启零拷贝技术 <a class="header-anchor" href="#开启零拷贝技术" aria-label="Permalink to &quot;开启零拷贝技术&quot;">​</a></h2><p>零拷贝这个概念，在大多数性能较为不错的中间件中都有出现，例如<code>Kafka、Netty</code>等，而<code>Nginx</code>中也可以配置数据零拷贝技术，如下：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">sendfile on</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 开启零拷贝机制</span></span></code></pre></div><p>零拷贝读取机制与传统资源读取机制的区别：</p><ul><li>传统方式：<strong>「硬件--&gt;内核--&gt;用户空间--&gt;程序空间--&gt;程序内核空间--&gt;网络套接字」</strong></li><li>零拷贝方式：<strong>「硬件--&gt;内核--&gt;程序内核空间--&gt;网络套接字」</strong></li></ul><p>从上述这个过程对比，很轻易就能看出两者之间的性能区别。</p><h2 id="开启无延迟或多包共发机制" tabindex="-1">开启无延迟或多包共发机制 <a class="header-anchor" href="#开启无延迟或多包共发机制" aria-label="Permalink to &quot;开启无延迟或多包共发机制&quot;">​</a></h2><p>在<code>Nginx</code>中有两个较为关键的性能参数，即<code>tcp_nodelay、tcp_nopush</code>，开启方式如下：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">tcp_nodelay on;</span></span>
<span class="line"><span style="color:#A6ACCD;">tcp_nopush on;</span></span></code></pre></div><p><code>TCP/IP</code>协议中默认是采用了Nagle算法的，即在网络数据传输过程中，每个数据报文并不会立马发送出去，而是会等待一段时间，将后面的几个数据包一起组合成一个数据报文发送，但这个算法虽然提高了网络吞吐量，但是实时性却降低</p><blockquote><p>因此你的项目属于交互性很强的应用，那么可以手动开启<code>tcp_nodelay</code>配置，让应用程序向内核递交的每个数据包都会立即发送出去。但这样会产生大量的<code>TCP</code>报文头，增加很大的网络开销。</p></blockquote><p>相反，有些项目的业务对数据的实时性要求并不高，追求的则是更高的吞吐，那么则可以开启<code>tcp_nopush</code>配置项，这个配置就类似于“塞子”的意思，首先将连接塞住，使得数据先不发出去，等到拔去塞子后再发出去。设置该选项后，内核会尽量把小数据包拼接成一个大的数据包（一个<code>MTU</code>）再发送出去.</p><blockquote><p>当然若一定时间后（一般为<code>200ms</code>），内核仍然没有积累到一个<code>MTU</code>的量时，也必须发送现有的数据，否则会一直阻塞。</p></blockquote><p><code>tcp_nodelay、tcp_nopush</code>两个参数是“互斥”的，如果追求响应速度的应用推荐开启<code>tcp_nodelay</code>参数，如<code>IM</code>、金融等类型的项目。如果追求吞吐量的应用则建议开启<code>tcp_nopush</code>参数，如调度系统、报表系统等。</p><blockquote><p>注意：①<code>tcp_nodelay</code>一般要建立在开启了长连接模式的情况下使用。②<code>tcp_nopush</code>参数是必须要开启<code>sendfile</code>参数才可使用的。</p></blockquote><h2 id="调整worker工作进程" tabindex="-1">调整Worker工作进程 <a class="header-anchor" href="#调整worker工作进程" aria-label="Permalink to &quot;调整Worker工作进程&quot;">​</a></h2><p><code>Nginx</code>启动后默认只会开启一个<code>Worker</code>工作进程处理客户端请求，而我们可以根据机器的CPU核数开启对应数量的工作进程，以此来提升整体的并发量支持，如下：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 自动根据CPU核心数调整Worker进程数量</span></span>
<span class="line"><span style="color:#A6ACCD;">worker_processes auto</span><span style="color:#89DDFF;">;</span></span></code></pre></div><blockquote><p>工作进程的数量最高开到<code>8</code>个就OK了，<code>8</code>个之后就不会有再大的性能提升。</p></blockquote><p>同时也可以稍微调整一下每个工作进程能够打开的文件句柄数：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 每个Worker能打开的文件描述符，最少调整至</span><span style="color:#F78C6C;">1W</span><span style="color:#A6ACCD;">以上，负荷较高建议</span><span style="color:#F78C6C;">2</span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">3W</span></span>
<span class="line"><span style="color:#A6ACCD;">worker_rlimit_nofile </span><span style="color:#F78C6C;">20000</span><span style="color:#89DDFF;">;</span></span></code></pre></div><blockquote><p>操作系统内核（<code>kernel</code>）都是利用文件描述符来访问文件，无论是打开、新建、读取、写入文件时，都需要使用文件描述符来指定待操作的文件，因此该值越大，代表一个进程能够操作的文件越多（但不能超出内核限制，最多建议<code>3.8W</code>左右为上限）。</p></blockquote><h2 id="开启cpu亲和机制" tabindex="-1">开启CPU亲和机制 <a class="header-anchor" href="#开启cpu亲和机制" aria-label="Permalink to &quot;开启CPU亲和机制&quot;">​</a></h2><p>对于并发编程较为熟悉的伙伴都知道，因为进程/线程数往往都会远超出系统CPU的核心数，因为操作系统执行的原理本质上是采用时间片切换机制，也就是一个CPU核心会在多个进程之间不断频繁切换，造成很大的性能损耗。</p><p>而CPU亲和机制则是指将每个<code>Nginx</code>的工作进程，绑定在固定的CPU核心上，从而减小CPU切换带来的时间开销和资源损耗，开启方式如下：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">worker_cpu_affinity auto</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h2 id="开启epoll模型及调整并发连接数" tabindex="-1">开启epoll模型及调整并发连接数 <a class="header-anchor" href="#开启epoll模型及调整并发连接数" aria-label="Permalink to &quot;开启epoll模型及调整并发连接数&quot;">​</a></h2><p>在最开始就提到过：<code>Nginx、Redis</code>都是基于多路复用模型去实现的程序，但最初版的多路复用模型<code>select/poll</code>最大只能监听<code>1024</code>个连接，而<code>epoll</code>则属于<code>select/poll</code>接口的增强版，因此采用该模型能够大程度上提升单个<code>Worker</code>的性能，如下：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">events </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 使用epoll网络模型</span></span>
<span class="line"><span style="color:#A6ACCD;">    use epoll</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">#</span><span style="color:#A6ACCD;"> 调整每个Worker能够处理的连接数上限</span></span>
<span class="line"><span style="color:#A6ACCD;">    worker_connections  </span><span style="color:#F78C6C;">10240</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><blockquote><p>这里对于<code>select/poll/epoll</code>模型就不展开细说了，后面的IO模型文章中会详细剖析。</p></blockquote><h2 id="禁用日志-日志缓冲" tabindex="-1">禁用日志 &amp; 日志缓冲 <a class="header-anchor" href="#禁用日志-日志缓冲" aria-label="Permalink to &quot;禁用日志 &amp; 日志缓冲&quot;">​</a></h2><p>访问日志记录，它记录每个nginx请求，因此消耗了大量CPU资源，从而降低了nginx性能</p><p>完全禁用访问日志记录</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">access_log off</span><span style="color:#89DDFF;">;</span></span></code></pre></div><p>如果必须具有访问日志记录，则启用访问日志缓冲</p><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#FFCB6B;">log_format</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">compression</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">$remote_addr - $remote_user [$time_local] </span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">                       </span><span style="color:#FFCB6B;">&#39;&quot;$request&quot; $status $bytes_sent &#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">                       </span><span style="color:#FFCB6B;">&#39;&quot;$http_referer&quot; &quot;$http_user_agent&quot; &quot;$gzip_ratio&quot;&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"># 设置日志缓冲区，只有达到缓冲区才会记录日志</span></span>
<span class="line"><span style="color:#FFCB6B;">access_log</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">/usr/local/nginx/logs/nginx-access.log</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">compression</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">buffer=</span><span style="color:#F78C6C;">1</span><span style="color:#C3E88D;">k</span><span style="color:#89DDFF;">;</span></span></code></pre></div><p>或者直接使用默认日志格式</p><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#FFCB6B;">access_log</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">/usr/local/nginx/logs/nginx-access.log</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">buffer</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">16</span><span style="color:#C3E88D;">k</span></span></code></pre></div><h2 id="为静态文件启用缓存" tabindex="-1">为静态文件启用缓存 <a class="header-anchor" href="#为静态文件启用缓存" aria-label="Permalink to &quot;为静态文件启用缓存&quot;">​</a></h2><p>为静态文件启用缓存，以减少带宽并提高性能，可以添加下面的命令，限定计算机缓存网页的静态文件：</p><div class="language-apl"><button title="Copy Code" class="copy"></button><span class="lang">apl</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">location </span><span style="color:#89DDFF;">~*</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">.(</span><span style="color:#A6ACCD;">jpg</span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;">jpeg</span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;">png</span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;">gif</span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;">ico</span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;">css</span><span style="color:#89DDFF;">|</span><span style="color:#A6ACCD;">js</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;">$ </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">     expires </span><span style="color:#F78C6C;">365d</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h1 id="https-调优" tabindex="-1">HTTPS 调优 <a class="header-anchor" href="#https-调优" aria-label="Permalink to &quot;HTTPS 调优&quot;">​</a></h1><h2 id="为什么要优化-ngin-https-延迟" tabindex="-1">为什么要优化 Ngin HTTPS 延迟 <a class="header-anchor" href="#为什么要优化-ngin-https-延迟" aria-label="Permalink to &quot;为什么要优化 Ngin HTTPS 延迟&quot;">​</a></h2><blockquote><p>Nginx 常作为最常见的服务器，常被用作负载均衡 (Load Balancer)、反向代理 (Reverse Proxy)，以及网关 (Gateway) 等等。一个配置得当的 Nginx 服务器单机应该可以期望承受住 50K 到 80K 左右每秒的请求，同时将 CPU 负载在可控范围内。</p></blockquote><blockquote><p>但在很多时候，负载并不是需要首要优化的重点。比如对于卡拉搜索来说，我们希望用户在每次击键的时候，可以体验即时搜索的感觉，也就是说，每个搜索请求必须在 100ms - 200ms 的时间内端对端地返回给用户，才能让用户搜索时没有“卡顿”和“加载”。因此，对于我们来说，优化请求延迟才是最重要的优化方向。</p></blockquote><blockquote><p>这篇文章中，我们先介绍 Nginx 中的 TLS 设置有哪些与请求延迟可能相关，如何调整才能最大化加速。然后我们用优化卡拉搜索 Nginx 服务器的实例来分享如何调整 Nginx TLS/SSL 设置，为首次搜索的用户提速 30% 左右。我们会详细讨论每一步我们做了一些什么优化，优化的动机和效果。希望可以对其它遇到类似问题的同学提供帮助。</p></blockquote><h2 id="tls-握手和延迟" tabindex="-1">TLS 握手和延迟 <a class="header-anchor" href="#tls-握手和延迟" aria-label="Permalink to &quot;TLS 握手和延迟&quot;">​</a></h2><blockquote><p>很多时候开发者会认为：如果不是绝对在意性能，那么了解底层和更细节的优化没有必要。这句话在很多时候是恰当的，因为很多时候复杂的底层逻辑必须包起来，才能让更高层的应用开发复杂度可控。比如说，如果你就只需要开发一个 APP 或者网站，可能并没有必要关注汇编细节，关注编译器如何优化你的代码——毕竟在苹果或者安卓上很多优化在底层就做好了。</p></blockquote><p>那么，了解底层的 TLS 和应用层的 Nginx 延迟优化有什么关系呢？</p><blockquote><p>答案是多数情况下，优化网络延迟其实是在尝试减少用户和服务器之间的数据传输次数，也就是所谓的 roundtrip。由于物理限制，北京到云南的光速传播差不多就是要跑 20 来毫秒，如果你不小心让数据必须多次往返于北京和云南之间，那么必然延迟就上去了。</p></blockquote><blockquote><p>因此如果你需要优化请求延迟，那么了解一点底层网络的上下文则会大有裨益，很多时候甚至是你是否可以轻松理解一个优化的关键。本文中我们不深入讨论太多 TCP 或者 TLS 机制的细节，如果有兴趣的话请参考 High Performance Browser Networking 一书，可以免费阅读。</p></blockquote><p>举个例子，下图中展示了如果你的服务启用了 HTTPS，在开始传输任何数据之前的数据传输情况。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/2rMyvdWluHuicvGcar1iaFjwZ9fO7yzcImPpb9iboDNjNEDDm8TIJsEWGv9acp9BNqybcNG49VZT6tRSkQuzhjYew/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><blockquote><p>在传输数据前数据已经跑了好几个来回 roundtrip 在传输数据前数据已经跑了好几个来回 roundtrip 可以看到，在你的用户拿到他需要的数据前，底层的数据包就已经在用户和你的服务器之间跑了 3 个来回。</p></blockquote><p>假设每次来回需要 28 毫秒的话，用户已经等了 224 毫秒之后才开始接收数据。</p><blockquote><p>同时这个 28 毫秒其实是非常乐观的假设，在国内电信、联通和移动以及各种复杂的网络状况下，用户与服务器之间的延迟更不可控。另一方面，通常一个网页需要数十个请求，这些请求不一定可以全部并行，因此几十乘以 224 毫秒，页面打开可能就是数秒之后了。</p></blockquote><blockquote><p>所以，原则上如果可能的话，我们需要尽量减少用户和服务器之间的往返程 (roundtrip)，在下文的设置中，对于每个设置我们会讨论为什么这个设置有可能帮助减少往返程。</p></blockquote><h2 id="nginx-中的-tls-设置" tabindex="-1">Nginx 中的 TLS 设置 <a class="header-anchor" href="#nginx-中的-tls-设置" aria-label="Permalink to &quot;Nginx 中的 TLS 设置&quot;">​</a></h2><p>那么在 Nginx 设置中，怎样调整参数会减少延迟呢？</p><h3 id="开启-http-2" tabindex="-1">开启 HTTP/2 <a class="header-anchor" href="#开启-http-2" aria-label="Permalink to &quot;开启 HTTP/2&quot;">​</a></h3><blockquote><p>HTTP/2 标准是从 Google 的 SPDY 上进行的改进，比起 HTTP 1.1 提升了不少性能，尤其是需要并行多个请求的时候可以显著减少延迟。在现在的网络上，一个网页平均需要请求几十次，而<strong>在 HTTP 1.1 时代浏览器能做的就是多开几个连接（通常是 6 个）进行并行请求</strong>，而 <strong>HTTP 2 中可以在一个连接中进行并行请求</strong>。HTTP 2 原生支持多个并行请求，因此大大减少了顺序执行的请求的往返程，可以首要考虑开启。</p></blockquote><p>如果你想自己看一下 HTTP 1.1 和 HTTP 2.0 的速度差异，可以试一下：<a href="https://www.httpvshttps.com/%E3%80%82%E6%88%91%E7%9A%84%E7%BD%91%E7%BB%9C%E6%B5%8B%E8%AF%95%E4%B8%8B%E6%9D%A5" target="_blank" rel="noreferrer">https://www.httpvshttps.com/。我的网络测试下来</a> HTTP/2 比 HTTP 1.1 快了 90%。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.2.30/202302031513784.png" alt="image-20230203151315656" style="zoom:67%;"><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.2.30/202302031513116.png" alt="image-20230203151347007" style="zoom:67%;"><p>在 Nginx 中开启 HTTP 2.0 非常简单，只需要增加一个 http2 标志即可</p><div class="language-sh"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#FFCB6B;">listen</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">ssl</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"># 改为</span></span>
<span class="line"><span style="color:#FFCB6B;">listen</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">443</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">ssl</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">http2</span><span style="color:#89DDFF;">;</span></span></code></pre></div><blockquote><p>如果你担心你的用户用的是旧的客户端，比如 Python 的 requests，暂时还不支持 HTTP 2 的话，l 那么其实不用担心。如果用户的客户端不支持 HTTP 2，那么连接会自动降级为 HTTP 1.1，保持了后向兼容。因此，所有使用旧 Client 的用户，仍然不受影响，而新的客户端则可以享受 HTTP/2 的新特性。</p></blockquote><h3 id="如何确认你的网站或者-api-开启了-http-2" tabindex="-1">如何确认你的网站或者 API 开启了 HTTP 2 <a class="header-anchor" href="#如何确认你的网站或者-api-开启了-http-2" aria-label="Permalink to &quot;如何确认你的网站或者 API 开启了 HTTP 2&quot;">​</a></h3><p>在 Chrome 中打开开发者工具，点开 Protocol 之后在所有的请求中都可以看到请求用的协议了。如果 protocol 这列的值是 h2 的话，那么用的就是 HTTP 2 了</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/2rMyvdWluHuicvGcar1iaFjwZ9fO7yzcImxQWHlMke9FibxvFNon1XnRPTqfjJdicXtibZLBDdLxJPXowp5D2fQKGIA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>当然另一个办法是直接用 curl 如果返回的 status 前有 HTTP/2 的话自然也就是 HTTP/2 开启了。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">➜  ~ curl --http2 -I https://kalasearch.cn</span></span>
<span class="line"><span style="color:#A6ACCD;">HTTP/2 403</span></span>
<span class="line"><span style="color:#A6ACCD;">server: Tengine</span></span>
<span class="line"><span style="color:#A6ACCD;">content-type: application/xml</span></span>
<span class="line"><span style="color:#A6ACCD;">content-length: 264</span></span>
<span class="line"><span style="color:#A6ACCD;">date: Tue, 22 Dec 2020 18:38:46 GMT</span></span>
<span class="line"><span style="color:#A6ACCD;">x-oss-request-id: 5FE23D363ADDB93430197043</span></span>
<span class="line"><span style="color:#A6ACCD;">x-oss-cdn-auth: success</span></span>
<span class="line"><span style="color:#A6ACCD;">x-oss-server-time: 0</span></span>
<span class="line"><span style="color:#A6ACCD;">x-alicdn-da-ups-status: endOs,0,403</span></span>
<span class="line"><span style="color:#A6ACCD;">via: cache13.l2et2[148,0], cache10.l2ot7[291,0], cache4.us13[360,0]</span></span>
<span class="line"><span style="color:#A6ACCD;">timing-allow-origin: *</span></span>
<span class="line"><span style="color:#A6ACCD;">eagleid: 2ff6169816086623266688093e</span></span></code></pre></div><h3 id="调整-cipher-优先级" tabindex="-1">调整 Cipher 优先级 <a class="header-anchor" href="#调整-cipher-优先级" aria-label="Permalink to &quot;调整 Cipher 优先级&quot;">​</a></h3><p>尽量挑选更新更快的 Cipher，有助于减少延迟:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;"># 手动启用 cipher 列表</span></span>
<span class="line"><span style="color:#A6ACCD;">ssl_prefer_server_ciphers on;  # prefer a list of ciphers to prevent old and slow ciphers</span></span>
<span class="line"><span style="color:#A6ACCD;">ssl_ciphers &#39;EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH&#39;;</span></span></code></pre></div><h3 id="启用-ocsp-stapling" tabindex="-1">启用 OCSP Stapling <a class="header-anchor" href="#启用-ocsp-stapling" aria-label="Permalink to &quot;启用 OCSP Stapling&quot;">​</a></h3><p>在国内这可能是对使用 Let&#39;s Encrypt 证书的服务或网站影响最大的延迟优化了。如果不启用 OCSP Stapling 的话，在用户连接你的服务器的时候，有时候需要去验证证书。而因为一些不可知的原因（这个就不说穿了）Let&#39;s Encrypt 的验证服务器并不是非常通畅，因此可以造成有时候数秒甚至十几秒延迟的问题，这个问题在 iOS 设备上特别严重</p><p>解决这个问题的方法有两个：</p><ol><li>不使用 Let&#39;s Encrypt，可以尝试替换为阿里云提供的免费 DV 证书</li><li>开启 OCSP Stapling</li></ol><p>开启了 OCSP Stapling 的话开启了 OCSP Stapling 的话，跑到证书验证这一步可以省略掉。省掉一个 roundtrip，特别是网络状况不可控的 roundtrip，可能可以将你的延迟大大减少。</p><p>在 Nginx 中启用 OCSP Stapling 也非常简单，只需要设置：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">ssl_stapling on;</span></span>
<span class="line"><span style="color:#A6ACCD;">ssl_stapling_verify on;</span></span>
<span class="line"><span style="color:#A6ACCD;">ssl_trusted_certificate /path/to/full_chain.pem;</span></span></code></pre></div><h3 id="如何检测-ocsp-stapling-是否已经开启" tabindex="-1">如何检测 OCSP Stapling 是否已经开启？ <a class="header-anchor" href="#如何检测-ocsp-stapling-是否已经开启" aria-label="Permalink to &quot;如何检测 OCSP Stapling 是否已经开启？&quot;">​</a></h3><p>可以通过以下命令</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">openssl s_client -connect test.kalasearch.cn:443 -servername kalasearch.cn -status -tlsextdebug &lt; /dev/null 2&gt;&amp;1 | grep -i &quot;OCSP response&quot;</span></span></code></pre></div><p>来测试。如果结果为</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">OCSP response:</span></span>
<span class="line"><span style="color:#A6ACCD;">OCSP Response Data:</span></span>
<span class="line"><span style="color:#A6ACCD;">    OCSP Response Status: successful (0x0)</span></span>
<span class="line"><span style="color:#A6ACCD;">    Response Type: Basic OCSP Response</span></span></code></pre></div><p>则表明已经开启。</p><h3 id="调整-ssl-buffer-size" tabindex="-1">调整 ssl_buffer_size <a class="header-anchor" href="#调整-ssl-buffer-size" aria-label="Permalink to &quot;调整 ssl_buffer_size&quot;">​</a></h3><p>sslbuffersize 控制在发送数据时的 buffer 大小，默认设置是 16k。这个值越小，则延迟越小，而添加的报头之类会使 overhead 会变大，反之则延迟越大，overhead 越小。</p><p>因此如果你的服务是 REST API 或者网站的话，将这个值调小可以减小延迟和 TTFB，但如果你的服务器是用来传输大文件的，那么可以维持 16k。</p><p>如果是网站或者 REST API，建议值为 4k，但是这个值的最佳取值显然会因为数据的不同而不一样，因此请尝试 2 - 16k 间不同的值。在 Nginx 中调整这个值也非常容易</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">sl_buffer_size 4k;</span></span></code></pre></div><h3 id="启用-ssl-session-缓存" tabindex="-1">启用 SSL Session 缓存 <a class="header-anchor" href="#启用-ssl-session-缓存" aria-label="Permalink to &quot;启用 SSL Session 缓存&quot;">​</a></h3><p>启用 SSL Session 缓存可以大大减少 TLS 的反复验证，减少 TLS 握手的 roundtrip。虽然 session 缓存会占用一定内存，但是用 1M 的内存就可以缓存 4000 个连接，可以说是非常非常划算的。同时，对于绝大多数网站和服务，要达到 4000 个同时连接本身就需要非常非常大的用户基数，因此可以放心开启。</p><p>这里 ssl_session_cache 设置为使用 50M 内存，以及 4 小时的连接超时关闭时间 ssl_session_timeout</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;"># Enable SSL cache to speed up for return visitors</span></span>
<span class="line"><span style="color:#A6ACCD;">ssl_session_cache   shared:SSL:50m; # speed up first time. 1m ~= 4000 connections</span></span>
<span class="line"><span style="color:#A6ACCD;">ssl_session_timeout 4h;</span></span></code></pre></div><h3 id="卡拉搜索如何减少-30-的请求延迟" tabindex="-1">卡拉搜索如何减少 30% 的请求延迟 <a class="header-anchor" href="#卡拉搜索如何减少-30-的请求延迟" aria-label="Permalink to &quot;卡拉搜索如何减少 30% 的请求延迟&quot;">​</a></h3><p>卡拉搜索是国内的 Algolia，致力于帮助开发者快速搭建即时搜索功能(instant search)，做国内最快最易用的搜索即服务。</p><p>开发者接入后，所有搜索请求通过卡拉 API 即可直接返回给终端用户。为了让用户有即时搜索的体验，我们需要在用户每次击键后极短的时间内（通常是 100ms 到 200ms）将结果返回给用户。因此每次搜索需要可以达到 50 毫秒以内的引擎处理时间和 200 毫秒以内的端对端时间。</p><blockquote><p>我们用豆瓣电影的数据做了一个电影搜索的 Demo，如果感兴趣的话欢迎体验一下即时搜索，尝试一下搜索“无间道”或者“大话西游”体验一下速度和相关度：<a href="https://movies-demo.kalasearch.cn/" target="_blank" rel="noreferrer">https://movies-demo.kalasearch.cn/</a></p></blockquote><p>对于每个请求只有 100 到 200 毫秒的延迟预算，我们必须把每一步的延迟都考虑在内。</p><p>简化一下，每个搜索请求需要经历的延迟有</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/2rMyvdWluHuicvGcar1iaFjwZ9fO7yzcImD0XKcBLC2yEe8gmu6QescFdH6N1mInHwutaic9OJgBdlRk2LdhfibEXw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>总延迟 = 用户请求到达服务器(T1) + 反代处理(Nginx T2) + 数据中心延迟(T3) + 服务器处理 (卡拉引擎 T4) + 用户请求返回(T3+T1)</p><p>在上述延迟中，T1 只与用户与服务器的物理距离相关，而 T3 非常小，可以忽略不计。</p><p>所以我们能控制的大致只有 T2 和 T4，即 Nginx 服务器的处理时间和卡拉的引擎处理时间。</p><p>Nginx 在这里作为反向代理，处理一些安全、流量控制和 TLS 的逻辑，而卡拉的引擎则是一个在 Lucene 基础上的倒排引擎。</p><p>我们首先考虑的第一个可能性是：延迟是不是来自卡拉引擎呢？</p><p>在下图展示的 Grafana 仪表盘中，我们看到除了几个时不时的慢查询，搜索的 95% 服务器处理延迟小于 20 毫秒。对比同样的数据集上 benchmark 的 Elastic Search 引擎的 P95 搜索延迟则在 200 毫秒左右，所以排除了引擎速度慢的可能。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/2rMyvdWluHuicvGcar1iaFjwZ9fO7yzcImS3wKJLicLgVetMl4akQjoxlw8QMZys1zvWKtrkdxSwIcF6ufQjffPFw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>而在阿里云监控中，我们设置了从全国各地向卡拉服务器发送搜索请求。我们终于发现 SSL 处理时间时常会超过 300 毫秒，也就是说在 T2 这一步，光处理 TLS 握手之类的事情，Nginx 已经用掉了我们所有的请求时间预算。</p><p>同时检查之后我们发现，在苹果设备上搜索速度格外慢，特别是第一次访问的设备。因此我们大致判断应该是因为我们使用的 Let&#39;s Encrypt 证书的问题。</p><p>我们按照上文中的步骤对 Nginx 设置进行了调整，并将步骤总结出来写了这篇文章。在调整了 Nginx TLS 的设置后，SSL 时间从平均的 140ms 降低到了 110ms 左右（全国所有省份联通和移动测试点），同时苹果设备上首次访问慢的问题也消失了。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/2rMyvdWluHuicvGcar1iaFjwZ9fO7yzcImQSKARmHkZdx6Kbf0ucHiaSRxXBTtCHcHdyfhQDEHrC6gOOAvAQkVN0Q/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>在调整过后，全国范围内测试的搜索延迟降低到了 150 毫秒左右。</p></div></div></main><footer class="VPDocFooter" data-v-6b87e69f data-v-37656e44><!--[--><!--]--><!----><nav class="prev-next" data-v-37656e44><div class="pager" data-v-37656e44><a class="pager-link prev" href="/notebook/Nginx/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-37656e44><span class="desc" data-v-37656e44>Previous page</span><span class="title" data-v-37656e44>基础篇</span></a></div><div class="pager" data-v-37656e44><a class="pager-link next" href="/notebook/Nginx/%E5%AE%9E%E6%88%98%E7%AF%87.html" data-v-37656e44><span class="desc" data-v-37656e44>Next page</span><span class="title" data-v-37656e44>实战篇</span></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>
    <script>window.__VP_HASH_MAP__=JSON.parse("{\"2、数据库_mysql_mysql面试_基础.md\":\"40da680a\",\"1、学前端_5、小程序_小程序项目.md\":\"60a1629b\",\"1、学前端_4、node_知识篇.md\":\"a7fb500e\",\"1、学前端_2、js_ts_es6 进阶.md\":\"6d07ba10\",\"1、学前端_3、vue_vue3_vue3进阶.md\":\"7ac622b4\",\"5、运维_jenkins.md\":\"929081f8\",\"1、学前端_2、js_ts_typescript.md\":\"875a4aa4\",\"2、数据库_mysql_mysql核心_设计.md\":\"7faf46d1\",\"2、数据库_mysql_mysql核心_基础.md\":\"d8e97f3e\",\"1、学前端_1、html_css_html基础.md\":\"7584d076\",\"1、学前端_5、专题篇_问题篇.md\":\"e893aaa2\",\"2、数据库_mysql_mysql面试_进阶.md\":\"f934806d\",\"3、springboot_运维_原理.md\":\"f4a39db6\",\"2、数据库_influxdb.md\":\"6e1711e1\",\"3、springboot_新特性.md\":\"cdf3e307\",\"mybatis_mybatisplus_jpa.md\":\"8e41681b\",\"1、学前端_5、小程序_小程序优化.md\":\"a2185198\",\"2、数据库_redis_redis基础.md\":\"856df0e0\",\"linux_实用脚本.md\":\"f2299dd5\",\"4、微服务_必备_分布式基础.md\":\"d49863d5\",\"2、数据库_redis_redis优化.md\":\"e66ae32f\",\"4、微服务_springsecurity_进阶篇.md\":\"235a8e9e\",\"5、运维_chatgpt.md\":\"10db3823\",\"2、数据库_mysql_分库分表.md\":\"e1c8a095\",\"start.md\":\"9bc1ff8d\",\"5、运维_github.md\":\"2ec6c735\",\"java学前端_css.md\":\"f11b47f0\",\"1、学前端_5、专题篇_知识篇.md\":\"a463ed8d\",\"linux_软件部署.md\":\"d6722925\",\"2、数据库_neo4j.md\":\"97ad22ac\",\"team.md\":\"ce467a6a\",\"nginx_实战篇.md\":\"7785486e\",\"index.md\":\"8c3ec167\",\"计算机基础_计算机网络_网络基础.md\":\"7a54a85d\",\"1、学前端_4、node_进阶篇.md\":\"60f6db69\",\"java_java集合.md\":\"a049b313\",\"1、学前端_3、vue_vue3_vue3高级.md\":\"614d1516\",\"1、学前端_5、小程序_微信小程序.md\":\"9a4be771\",\"5、运维_netty.md\":\"12ca0278\",\"2、数据库_mysql_mysql核心_运维.md\":\"83f97c16\",\"idea_vs code.md\":\"afdcb593\",\"java学前端_vue3_组件.md\":\"1086884e\",\"idea_chrome.md\":\"4a32afbc\",\"云原生_k8s.md\":\"db58e65a\",\"2、数据库_mysql_mysql核心_进阶.md\":\"61d16dff\",\"ssm_springbatch.md\":\"f799ab4a\",\"三高_分布式.md\":\"db1b8a1b\",\"2、数据库_elasticsearch_1、es基础.md\":\"04d17448\",\"linux_linux基础.md\":\"4b0bf394\",\"idea_idea插件.md\":\"fa86e45a\",\"可视化 _ 监控_可视化大屏.md\":\"004553bd\",\"2、数据库_mongodb_整合.md\":\"3c47d7f4\",\"4、微服务_springsecurity_基础篇.md\":\"534a3401\",\"4、微服务_进阶.md\":\"69095c58\",\"计算机基础_计算机基础_操作系统.md\":\"0f75d113\",\"可视化 _ 监控_zabbix.md\":\"71f2270e\",\"nginx_基础篇.md\":\"c7d8bb50\",\"1、学前端_4、node_项目实战.md\":\"bc5065b8\",\"2、数据库_redis_redis原理.md\":\"5cedf685\",\"可视化 _ 监控_监控基础.md\":\"ac56ce4d\",\"三高_高并发.md\":\"ea9ffc99\",\"2、数据库_redis_redis高级.md\":\"1d5872f6\",\"1、学前端_4、node_基础篇.md\":\"581cc13a\",\"2、数据库_mongodb_基础.md\":\"fb7a0a29\",\"idea_idea基础.md\":\"6f2f9638\",\"4、微服务_必备_sentinel.md\":\"2edfbf6c\",\"2、数据库_elasticsearch_3、es高级.md\":\"ef146606\",\"1、学前端_3、vue_vue3_vue3新语法.md\":\"8afd5409\",\"消息中间件_canal.md\":\"3949163c\",\"ssm_maven.md\":\"2c5e12ed\",\"4、微服务_springsecurity_高级篇.md\":\"882d3ff3\",\"linux_linux进阶.md\":\"188ef7b4\",\"计算机基础_设计模式_uml.md\":\"634ba256\",\"计算机基础_算法_leetcode.md\":\"77162fb9\",\"项目实战_小兔鲜_进阶篇1.md\":\"17c52c81\",\"1、学前端_2、js_ts_es6 基础.md\":\"fda3f18b\",\"项目实战_小兔鲜_进阶篇2.md\":\"a0f23006\",\"软件测试_测试基础.md\":\"8c1060cd\",\"2、数据库_redis_本地缓存.md\":\"00617fe6\",\"nginx_面试篇.md\":\"e3fb373a\",\"mybatis_mybatisplus_mybatis.md\":\"9239e0ad\",\"linux_shell.md\":\"ae53d83b\",\"2、数据库_mysql_mysql核心_优化.md\":\"36230425\",\"项目实战_项目推荐.md\":\"f9d97630\",\"mybatis_mybatisplus_mybatisplus.md\":\"0030fd35\",\"项目实战_百度地图_进阶篇.md\":\"c8b93267\",\"三高_高可用.md\":\"323840c5\",\"java_java新特性.md\":\"22abf56d\",\"软件测试_压力测试.md\":\"9ab44440\",\"java学前端_html_js.md\":\"e0fcd240\",\"2、数据库_redis_redis实战.md\":\"d6daeeab\",\"nginx_进阶篇.md\":\"e6b63195\",\"三高_秒杀.md\":\"3878bb64\",\"5、运维_git.md\":\"0264925c\",\"java_java进阶.md\":\"e79cb5b4\",\"并发 _ 多线程_基础篇.md\":\"7adbfac5\",\"项目实战_百度地图_基础篇.md\":\"8afa5954\",\"java学前端_react.md\":\"3ec827dd\",\"1、学前端_1、html_css_css基础.md\":\"01b56712\",\"项目实战_小兔鲜_基础篇.md\":\"646f5df5\",\"1、学前端_2、js_ts_js 基础.md\":\"cb13e36f\",\"可视化 _ 监控_监控进阶.md\":\"0cdbc292\",\"计算机基础_设计模式_基础篇.md\":\"51617287\",\"计算机基础_数据结构_基础篇.md\":\"b2bfd8d4\",\"项目实战_苍穹外卖_进阶篇.md\":\"48415e41\",\"ssm_spring.md\":\"ab514659\",\"消息中间件_rabbitmq.md\":\"45b1eb28\",\"1、学前端_1、html_css_网页进阶.md\":\"db998248\",\"消息中间件_kafka.md\":\"b747dabf\",\"云原生_docker.md\":\"983c7ba7\",\"4、微服务_必备_分布式锁.md\":\"5af1cf8d\",\"消息中间件_rocketmq.md\":\"d441da85\",\"项目实战_黑马头条_基础篇.md\":\"b05af3a6\",\"ssm_springmvc.md\":\"81b9714f\",\"项目实战_支付.md\":\"1d7407dd\",\"项目实战_黑马头条_进阶篇2.md\":\"bff0015b\",\"项目实战_黑马头条_进阶篇.md\":\"19f18388\",\"java学前端_vue2_组件.md\":\"58c6b1df\",\"3、springboot_基础篇.md\":\"529c66f4\",\"3、springboot_应用篇.md\":\"8b92aa61\",\"项目实战_黑马头条_高级篇.md\":\"227c08c1\",\"1、学前端_5、小程序_uniapp.md\":\"71a282b4\",\"项目实战_云尚办公_基础篇.md\":\"1fe188ba\",\"并发 _ 多线程_并发完善.md\":\"26619c46\",\"1、学前端_2、js_ts_js 进阶.md\":\"657dfb8f\",\"java_java高级.md\":\"23782d1a\",\"java_java基础.md\":\"86d67c77\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"VitePress\",\"description\":\"A VitePress site\",\"base\":\"/notebook/\",\"head\":[],\"appearance\":true,\"themeConfig\":{\"algolia\":{\"appId\":\"DW7O63I9IR\",\"apiKey\":\"f8ed758cdb288a8b06542bc35923c1a1\",\"indexName\":\"notebook\"},\"sidebar\":[{\"text\":\"Java\",\"collapsed\":true,\"items\":[{\"text\":\"Java基础\",\"link\":\"/Java/Java基础\"},{\"text\":\"Java新特性\",\"link\":\"/Java/Java新特性\"},{\"text\":\"Java进阶\",\"link\":\"/Java/Java进阶\"},{\"text\":\"Java集合\",\"link\":\"/Java/Java集合\"},{\"text\":\"Java高级\",\"link\":\"/Java/Java高级\"}]},{\"text\":\"Linux\",\"collapsed\":true,\"items\":[{\"text\":\"Linux基础\",\"link\":\"/Linux/Linux基础\"},{\"text\":\"Linux新特性\",\"link\":\"/Linux/Linux进阶\"},{\"text\":\"Shell脚本\",\"link\":\"/Linux/Shell\"},{\"text\":\"实用脚本\",\"link\":\"/Linux/实用脚本\"},{\"text\":\"软件部署\",\"link\":\"/Linux/软件部署\"}]},{\"text\":\"Nginx\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/Nginx/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/Nginx/进阶篇\"},{\"text\":\"实战篇\",\"link\":\"/Nginx/实战篇\"},{\"text\":\"面试篇\",\"link\":\"/Nginx/面试篇\"}]},{\"text\":\"SSM\",\"collapsed\":true,\"items\":[{\"text\":\"Maven\",\"link\":\"/SSM/Maven\"},{\"text\":\"Spring\",\"link\":\"/SSM/Spring\"},{\"text\":\"SpringMVC\",\"link\":\"/SSM/SpringMVC\"},{\"text\":\"SpringBatch\",\"link\":\"/SSM/SpringBatch\"}]},{\"text\":\"SpringBoot\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/3、SpringBoot/基础篇\"},{\"text\":\"应用篇\",\"link\":\"/3、SpringBoot/应用篇\"},{\"text\":\"新特性\",\"link\":\"/3、SpringBoot/新特性\"},{\"text\":\"运维&原理\",\"link\":\"/3、SpringBoot/运维&原理\"}]},{\"text\":\"SpringCloud\",\"collapsed\":true,\"items\":[{\"text\":\"SpringCloud\",\"link\":\"/4、微服务/进阶\"},{\"text\":\"Sentinel\",\"link\":\"/4、微服务/必备/Sentinel\"}]},{\"text\":\"SpringSecurity\",\"collapsed\":true,\"items\":[{\"text\":\"SpringSecurity基础篇\",\"link\":\"/4、微服务/SpringSecurity/基础篇\"},{\"text\":\"SpringSecurity进阶篇\",\"link\":\"/4、微服务/SpringSecurity/进阶篇\"},{\"text\":\"SpringSecurity高级篇\",\"link\":\"/4、微服务/SpringSecurity/高级篇\"}]},{\"text\":\"Mybatis & MybatisPlus\",\"collapsed\":true,\"items\":[{\"text\":\"Mybatis\",\"link\":\"/Mybatis&MybatisPlus/Mybatis\"},{\"text\":\"MybatisPlus\",\"link\":\"/Mybatis&MybatisPlus/MybatisPlus\"},{\"text\":\"JPA\",\"link\":\"/Mybatis&MybatisPlus/JPA\"}]},{\"text\":\"Git & ChatGPT\",\"collapsed\":true,\"items\":[{\"text\":\"Git\",\"link\":\"/5、运维/Git\"},{\"text\":\"Github\",\"link\":\"/5、运维/Github\"},{\"text\":\"ChatGPT\",\"link\":\"/5、运维/ChatGPT\"},{\"text\":\"Jenkins\",\"link\":\"/5、运维/Jenkins\"},{\"text\":\"Netty\",\"link\":\"/5、运维/Netty\"}]},{\"text\":\"数据库\",\"collapsed\":true,\"items\":[{\"text\":\"MySQL\",\"collapsed\":true,\"items\":[{\"text\":\"MySQL基础\",\"link\":\"/2、数据库/MySQL/MySQL核心/基础\"},{\"text\":\"MySQL进阶\",\"link\":\"/2、数据库/MySQL/MySQL核心/进阶\"},{\"text\":\"MySQL优化\",\"link\":\"/2、数据库/MySQL/MySQL核心/优化\"},{\"text\":\"MySQL设计\",\"link\":\"/2、数据库/MySQL/MySQL核心/设计\"},{\"text\":\"MySQL运维\",\"link\":\"/2、数据库/MySQL/MySQL核心/运维\"},{\"text\":\"分库分表\",\"link\":\"/2、数据库/MySQL/分库分表\"}]},{\"text\":\"Redis\",\"collapsed\":true,\"items\":[{\"text\":\"Redis基础\",\"link\":\"/2、数据库/Redis/Redis基础\"},{\"text\":\"Redis优化\",\"link\":\"/2、数据库/Redis/Redis优化\"},{\"text\":\"Redis原理\",\"link\":\"/2、数据库/Redis/Redis原理\"},{\"text\":\"Redis高级\",\"link\":\"/2、数据库/Redis/Redis高级\"},{\"text\":\"Redis实战\",\"link\":\"/2、数据库/Redis/Redis实战\"},{\"text\":\"本地缓存\",\"link\":\"/2、数据库/Redis/本地缓存\"}]},{\"text\":\"MongoDB\",\"collapsed\":true,\"items\":[{\"text\":\"MongoDB基础\",\"link\":\"/2、数据库/MongoDB/基础\"},{\"text\":\"MongoDB进阶\",\"link\":\"/2、数据库/MongoDB/整合\"}]},{\"text\":\"ElasticSearch\",\"collapsed\":true,\"items\":[{\"text\":\"ES基础\",\"link\":\"/2、数据库/ElasticSearch/1、ES基础\"},{\"text\":\"ES高级\",\"link\":\"/2、数据库/ElasticSearch/3、ES高级\"}]},{\"text\":\"InfluxDB\",\"link\":\"/2、数据库/influxdb\"},{\"text\":\"Neo4j\",\"link\":\"/2、数据库/Neo4j\"}]},{\"text\":\"高并发 & 秒杀 & 分布式\",\"collapsed\":true,\"items\":[{\"text\":\"分布式理论\",\"link\":\"/三高/分布式\"},{\"text\":\"分布式锁\",\"link\":\"/4、微服务/必备/分布式锁\"},{\"text\":\"秒杀\",\"link\":\"/三高/秒杀\"},{\"text\":\"高可用\",\"link\":\"/三高/高可用\"},{\"text\":\"高并发\",\"link\":\"/三高/高并发\"}]},{\"text\":\"云原生\",\"collapsed\":true,\"items\":[{\"text\":\"Docker\",\"link\":\"/云原生/Docker\"},{\"text\":\"K8S\",\"link\":\"/云原生/K8S\"}]},{\"text\":\"可视化 & 监控\",\"collapsed\":true,\"items\":[{\"text\":\"监控基础\",\"link\":\"/可视化 & 监控/监控基础\"},{\"text\":\"监控进阶\",\"link\":\"/可视化 & 监控/监控进阶\"},{\"text\":\"可视化大屏\",\"link\":\"/可视化 & 监控/可视化大屏\"},{\"text\":\"Zabbix\",\"link\":\"/可视化 & 监控/Zabbix\"}]},{\"text\":\"学前端\",\"collapsed\":true,\"items\":[{\"text\":\"HTML+CSS\",\"collapsed\":true,\"items\":[{\"text\":\"HTML基础\",\"link\":\"/1、学前端/1、HTML+CSS/HTML基础\"},{\"text\":\"CSS基础\",\"link\":\"/1、学前端/1、HTML+CSS/CSS基础\"},{\"text\":\"网页进阶\",\"link\":\"/1、学前端/1、HTML+CSS/网页进阶\"}]},{\"text\":\"JS+TS\",\"collapsed\":true,\"items\":[{\"text\":\"JS基础\",\"link\":\"/1、学前端/2、JS+TS/JS 基础\"},{\"text\":\"JS进阶\",\"link\":\"/1、学前端/2、JS+TS/JS 进阶\"},{\"text\":\"ES6基础\",\"link\":\"/1、学前端/2、JS+TS/ES6 基础\"},{\"text\":\"ES6进阶\",\"link\":\"/1、学前端/2、JS+TS/ES6 进阶\"},{\"text\":\"TS基础\",\"link\":\"/1、学前端/2、JS+TS/TypeScript\"}]},{\"text\":\"NodeJS\",\"collapsed\":true,\"items\":[{\"text\":\"Node基础\",\"link\":\"/1、学前端/4、Node/基础篇\"},{\"text\":\"Node进阶\",\"link\":\"/1、学前端/4、Node/进阶篇\"},{\"text\":\"项目实战\",\"link\":\"/1、学前端/4、Node/项目实战\"}]},{\"text\":\"Vue\",\"collapsed\":true,\"items\":[{\"text\":\"Vue3进阶\",\"link\":\"/1、学前端/3、Vue/Vue3/Vue3进阶\"},{\"text\":\"Vue3高级\",\"link\":\"/1、学前端/3、Vue/Vue3/Vue3高级\"},{\"text\":\"Vue3新语法\",\"link\":\"/1、学前端/3、Vue/Vue3/Vue3新语法\"},{\"text\":\"项目实战\",\"link\":\"/1、学前端/3、Vue/Vue2/Vue2项目\"}]},{\"text\":\"小程序\",\"collapsed\":true,\"items\":[{\"text\":\"小程序基础\",\"link\":\"/1、学前端/5、小程序/微信小程序\"},{\"text\":\"小程序优化\",\"link\":\"/1、学前端/5、小程序/小程序优化\"},{\"text\":\"uniapp\",\"link\":\"/1、学前端/5、小程序/uniapp\"},{\"text\":\"项目实战\",\"link\":\"/1、学前端/5、小程序/小程序项目\"}]}]},{\"text\":\"计算机基础\",\"collapsed\":true,\"items\":[{\"text\":\"数据结构\",\"link\":\"/计算机基础/数据结构/基础篇\"},{\"text\":\"操作系统\",\"link\":\"/计算机基础/计算机基础/操作系统\"},{\"text\":\"设计模式\",\"link\":\"/计算机基础/设计模式/基础篇\"},{\"text\":\"计算机网络\",\"link\":\"/计算机基础/计算机网络/网络基础\"},{\"text\":\"UML\",\"link\":\"/计算机基础/设计模式/UML\"},{\"text\":\"LeetCode\",\"link\":\"/计算机基础/算法/LeetCode\"}]},{\"text\":\"项目实战\",\"collapsed\":true,\"items\":[{\"text\":\"云尚办公\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/云尚办公/基础篇\"}]},{\"text\":\"小兔鲜\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/小兔鲜/基础篇\"},{\"text\":\"进阶篇1\",\"link\":\"/项目实战/小兔鲜/进阶篇1\"},{\"text\":\"进阶篇2\",\"link\":\"/项目实战/小兔鲜/进阶篇2\"}]},{\"text\":\"地图\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/百度地图/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/项目实战/百度地图/进阶篇\"}]},{\"text\":\"苍穹外卖\",\"collapsed\":true,\"items\":[{\"text\":\"进阶篇\",\"link\":\"/项目实战/苍穹外卖/进阶篇\"}]},{\"text\":\"黑马头条\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/黑马头条/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/项目实战/黑马头条/进阶篇\"},{\"text\":\"进阶篇2\",\"link\":\"/项目实战/黑马头条/进阶篇2\"},{\"text\":\"高级篇\",\"link\":\"/项目实战/黑马头条/高级篇\"}]},{\"text\":\"支付\",\"link\":\"/项目实战/支付\"},{\"text\":\"项目推荐\",\"link\":\"/项目实战/项目推荐\"}]},{\"text\":\"团队成员\",\"link\":\"/team\"}],\"siteTitle\":\"任硕的文档\",\"logo\":\"/Vue.png\",\"nav\":[{\"text\":\"Java学前端\",\"items\":[{\"items\":[{\"text\":\"HTML+JS\",\"link\":\"/Java学前端/HTML+JS\"},{\"text\":\"CSS\",\"link\":\"/Java学前端/CSS\"},{\"text\":\"Vue2+组件\",\"link\":\"/Java学前端/Vue2+组件\"},{\"text\":\"Vue3+组件\",\"link\":\"/Java学前端/Vue3+组件\"},{\"text\":\"React\",\"link\":\"/Java学前端/React\"}]}],\"activeMatch\":\"/Java/\"},{\"text\":\"软件测试\",\"items\":[{\"items\":[{\"text\":\"测试基础\",\"link\":\"/软件测试/测试基础\"},{\"text\":\"压力测试\",\"link\":\"/软件测试/压力测试\"}]}]},{\"text\":\"多线程\",\"items\":[{\"items\":[{\"text\":\"基础篇\",\"link\":\"/并发 & 多线程/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/并发 & 多线程/并发完善\"}]}]},{\"text\":\"开发工具\",\"items\":[{\"items\":[{\"text\":\"Chrome\",\"link\":\"/IDEA/Chrome\"},{\"text\":\"IDEA基础\",\"link\":\"/IDEA/IDEA基础\"},{\"text\":\"IDEA插件\",\"link\":\"/IDEA/IDEA插件\"},{\"text\":\"VS Code\",\"link\":\"/IDEA/VS Code\"}]}]},{\"text\":\"消息中间件\",\"items\":[{\"items\":[{\"text\":\"RabbitMQ\",\"link\":\"/消息中间件/RabbitMQ\"},{\"text\":\"RocketMQ\",\"link\":\"/消息中间件/RocketMQ\"},{\"text\":\"Kafka\",\"link\":\"/消息中间件/Kafka\"},{\"text\":\"Canal\",\"link\":\"/消息中间件/Canal\"}]}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/renshuo123/renshuo123.github.io\"},{\"icon\":\"twitter\",\"link\":\"#\"},{\"icon\":{\"svg\":\"<svg t=\\\"1676028692954\\\" class=\\\"icon\\\" ...</path></svg>\"},\"link\":\"https://github.com/\"}]},\"locales\":{},\"scrollOffset\":90,\"cleanUrls\":false}");</script>
    
  </body>
</html>